我学习Haskell和我目前发现的数据成员的访问器“。 假设我有一些虚拟的2D顶点信息,一类是有一定的颜色,比有一定的纹理坐标其他(TC):哈斯克尔访问器为不存在的记录
data SVertex = VertexC (Float, Float) Int
| VertexTC (Float, Float) (Float, Float)
deriving(Show)
一个繁琐的方法来创建存取记载是编写与图形的功能:现在
position (VertexC (x,y) c) = (x,y)
position (VertexTC (x,y) c) = (x,y)
tc (VertexTC _ tc) = tc
color :: SVertex -> Int
color (VertexC _ c) = c
,一个积极的特点是,我能为那些没有“色”或“TC”的那些添加存取(“颜色”和“TC”):
position (VertexC (x,y) c) = (x,y)
position (VertexTC (x,y) c) = (x,y) -- no header, here... still works
tc (VertexTC _ tc) = tc
tc (VertexC _ _) = (0,0) -- to returns something even if the field doesn't exist
color :: SVertex -> Int
color (VertexC _ c) = c
color (VertexTC _ _) = 0 -- return something even if field doesn't exist
它允许我给默认的0值的顶点没有任何纹理坐标或颜色0的顶点,没有颜色... 所有好...
现在,我的问题:我现在正在阅读,有一个很好的方法可以将访问者名称直接放入数据声明中。 在我这里的情况是什么,我会(使用“黄金”,以避免名称冲突)获得:
data SVertex' = VertexC' {
position' :: (Float, Float),
color' :: Int
}
| VertexTC' {
position' :: (Float, Float),
tc' :: (Float, Float)
} deriving(Show)
这样我就可以达到同样的目标:“位置“”,“TC””和“色''访问器是为我创建的!
但是:我没有找到一种方法来为不存在的字段提供默认访问器。例如,当在'VertexC'上请求tc时;或在VertexTC上请求颜色... 在第一种方法上,我可以做到这一点。在这种方便的第二种方法中,我担心这是不可能的。 当我尝试添加其他功能模式像
color' (VertexTC' _ _) = 0
编译器告诉我“‘色’等多次声明”。而现在看来似乎是因为本次声明没有做以下由编译器生成以前隐含一个...
你知道解决方法吗?
我不相信这是可能的。一般来说,Haskell记录是一个痛苦点(特别是它们是部分的,这就是你所得到的)。如果你对记录感兴趣,你可能最终会在某个时候检查出['lens'](https://hackage.haskell.org/package/lens)(这个偏好是用“Prism”抽象来处理的)。 – Alec
这是不可能的,但它也是非惯用Haskell的一个指标。当你使用'SVertex'实例来处理这些默认值时,考虑更多地使用模式匹配,而不是制定一个全局规则(后一种方法感觉Java非常流行)。 –
我没有意识到访问'记录'在Haskell中存在如此的缺陷。感谢您确认我应该如何意识到这一点。 似乎有些人正试图改善这个范围内的事情:http://nikita-volkov.github.io/record/ –