为什么Haskell中的元组没有“通用”访问器函数?

时间:2013-03-12 09:00:15

标签: haskell typeclass

我知道有fstsnd,但是为什么使用类型类这样的访问器函数没有“通用”定义?我会建议像

这样的东西
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 

当然,你需要一些语言扩展,但这不是很多更方便吗?特别是您可以为自己的类型添加实例。

2 个答案:

答案 0 :(得分:7)

需要注意的一点是fstsnd只允许一个人查看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上有许多包为任意长度的元组提供索引函数。