我知道有fst
和snd
,但是为什么使用类型类这样的访问器函数没有“通用”定义?我会建议像
class Get1 p a | p -> a where
get1 :: p -> a
instance Get1 (a,b) a where
get1 (x,_) = x
instance Get1 (a,b,c) a where
get1 (x,_,_) = x
class Get2 p a | p -> a where
get2 :: p -> a
instance Get2 (a,b) b where
get2 (_,x) = x
instance Get2 (a,b,c) b where
get2 (_,x,_) = x
当然,你需要一些语言扩展,但这不是很多更方便吗?特别是您可以为自己的类型添加实例。
答案 0 :(得分:7)
需要注意的一点是fst
和snd
只允许一个人查看2元组。将它们推广到其他智能和操作很快就会变得很痛苦。例如,如果你想要映射元组的第一个元素,你必须引入另一个组合子(对于记录,它存在于2元组中作为Control.Arrow.first
)。这很快导致高级元组的组合数量激增。
话虽这么说,lens
提供了一些很好的工具来处理元组。 Control.Lens.Tuple
提供了几个索引镜头_1
,_2
等,可以访问元组9的第一个,第二个等元素。
例如,
>>> import Control.Lens
>>> let t = (1,2,3,5,6,7,2)
>>> t ^._1
1
>>> t & _1 .~ 'a'
('a',2,3,5,6,7,2)
>>> t & _1 +~ 41
(42,2,3,5,6,7,2)
>>> over _1 (+1) t
(2,2,3,5,6,7,2)
您可能也对Control.Lens.At
中的元组实例感兴趣。此外,tuple-lenses
package提供了一些更通用的镜头,可以同时检查多个元组条目。
答案 1 :(得分:3)
这种类型类只提供编码(语法)方便,我没有看到如何在它们上构建通用的元组类型工具。如果您正在寻找元组概括,请在Reddit上查看the discussion about heterogeneous vectors。
另请注意,对于普通结构,最好定义自己的ADT并为getter提供合理的名称,然后使用高元组。
编辑:但是,正如注释中指出的is7s一样,hackage上有许多包为任意长度的元组提供索引函数。