此问题与Edward A. Kmett的lens package(版本4.13)有关
我有许多不同的data
类型,所有这些类型都有一个表示所包含元素的最大数量的字段(业务规则会在运行时发生变化,而不是集合实现问题)。在所有情况下,我都希望将此字段称为capacity
,但很快就遇到了命名空间冲突。
我在lens
文档中看到有一个makeClassy
模板,但是我找不到我能理解的文档。这个模板函数允许我拥有多个具有相同字段名称的镜头吗?
EDITED:让我补充一点,我非常有能力围绕这个问题进行编码。我想知道makeClassy
是否会解决这个问题。
3条答案
按热度按时间eimct9ow1#
我发现文档也有点不清楚;我不得不通过实验来弄清楚控制器、透镜和TH做了什么。
您需要的是
makeFields
:然后在ghci中:
所以它实际上做的是声明一个类
HasCapacity s a
,这里的capacity是从s
到a
的Lens'
(一旦s
已知,a
就固定了),它通过从字段中剥离数据类型的名称(小写)得出名称capacity
;我发现不用在字段名或透镜名上使用下划线是很愉快的,因为有时候记录语法实际上就是你想要的,你可以使用makeFieldsWith
和各种lensRules
来计算镜头名。如果有用,使用
ghci -ddump-splices Foo.hs
:因此,第一个拼接生成了类
HasCapacity
,并为Foo
添加了一个示例;第二个使用现有的类并为Bar
创建一个示例。如果您从另一个模块导入
HasCapacity
类,也可以这样做;makeFields
可以向现有的类添加更多示例,并将类型分散到多个模块中,但是如果您在另一个模块中再次使用它,而您 * 还没有 * 导入该类,它将生成一个 * 新 * 类(具有相同的名称),并且您将拥有两个独立的重载capacity
镜头,这两个镜头不兼容。makeClassy
有点不同。如果我有:(注意
makeClassy
希望您在字段上使用下划线前缀,而不是数据类型名称)然后,再次使用
-ddump-splices
:它创建的类是
HasFoo
,而不是HasCapacity
;它说的是,任何东西,只要你能得到一个Foo,你就能得到Foo
的容量,还有类,硬编码capacity
是一个Int
,而不是像makeFields
那样重载它,所以这仍然有效(因为HasFoo Foo
,在这里您只需使用id
即可获得Foo
):但是你不能用这个
capacity
透镜也得到一个不相关的类型的能力。ss2ws0br2#
模板是可选的;你可以自己制作类和镜头。
现在,任何具有容量的类型都可以成为该类的示例。
另一种方法是分解容量:
4xrmg8kj3#
在字段名前面加上下划线和数据类型名称,然后使用
makeFields
: