Haskell 访问元组中的特定元素

Haskell 访问元组中的特定元素,haskell,functional-programming,tuples,Haskell,Functional Programming,Tuples,哈斯凯尔新手在报道。 问题如下: 在Haskell中,我们有fst和snd,它们返回2元组的第一个和第二个元素。为什么我们没有一种从任何元组访问第i个元素的简单方法呢?现在我有一个3元组,我想读第一个元素,完成这个任务的唯一方法就是做模式匹配的技巧。为什么这样做不容易?或者可能有一些简单的方法?阻止语言具有您想要的特殊结构的是它的设计。设计师只是没有把它放进去,因为它会使语言定义复杂化,这是非常简单的fst和snd是成对常见情况下的库函数;您可以自己定义所有其他类型,或者更好地为数据定义记录类型

哈斯凯尔新手在报道。 问题如下:
在Haskell中,我们有
fst
snd
,它们返回2元组的第一个和第二个元素。为什么我们没有一种从任何元组访问第i个元素的简单方法呢?现在我有一个3元组,我想读第一个元素,完成这个任务的唯一方法就是做模式匹配的技巧。为什么这样做不容易?或者可能有一些简单的方法?

阻止语言具有您想要的特殊结构的是它的设计。设计师只是没有把它放进去,因为它会使语言定义复杂化,这是非常简单的
fst
snd
是成对常见情况下的库函数;您可以自己定义所有其他类型,或者更好地为数据定义记录类型,以便数据成员具有适当的名称


(可能是GHC有一个扩展来做这件事,但我没有遇到过;检查文档或询问邮件列表以确定。)

使用模板haskell来做这件事的方法是什么

其用法示例如下:

> $(sel 2 3) ('a','b','c') 'b' > $(sel 3 4) ('a','b','c','d') 'c' >$(选择2 3)(“a”、“b”、“c”) “b” >$(选择34)('a'、'b'、'c'、'd') “c” .

N元组不是通过
Int
键进行索引的数据结构,相反,您应该查看一个有索引偏差的数据结构,例如或

现在,我们可以想象这样写了,但是,我们已经有了数组,并且有很多必要的样板文件来让任何类型的元组无缝地提供这个操作。所获得的力量不值得付出努力。

请查看有关黑客的信息。它为元组上的各种操作(最大为预定义大小)提供了重载函数

为什么这样做不容易?或者有什么简单的方法

使用最新的替代方案会更容易 包裹具有最多9个元素元组的选择器,如果需要,可以直接定义更多元素元组

> import Control.Lens
> data A = A deriving (Show)
> (1, '2', "3", A) ^. _1
1
> (1, '2', "3", A) ^. _2
'2'
> (1, '2', "3", A) ^. _3
"3"
> (1, '2', "3", A) ^. _4
A
您也可以使用 包以多态方式更新元素,在更新时更改类型

使用和不使用中缀运算符:

> (1, '2', "3", A) & _1 .~ "wow"
("wow",'2',"3",A)
 > set _1 "wow" (1, '2', "3", A)
("wow",'2',"3",A)
这是一个很好的开始,以了解更多的基本理论以及大量的例子


不仅仅是元组 类似的语法适用于
Traverables
Foldables
,因此树、映射、向量等等。例如,如果我有一个元组列表,我可以通过组合
元素1
来访问第一个索引元素
\u 3
来访问第三个元组元素,从而访问1索引处的第三个元组元素

[(1,2,3),(4,5,6),(7,8,9)] ^? element 1 . _3
Just 6
尼基塔·沃尔科夫(Nikita Volkov)的新功能似乎可以满足你的需求。在链接页面上搜索标题“元组也是记录!”


看起来这个库还在开发中,所以现在安装和使用起来可能不像将来那么容易。

第三(,,x)=x有什么问题吗??这正是我要说的。是什么阻止了语言拥有一个特殊的构造,从而避免了我们编写您提到的函数的麻烦?这样的构造是什么样的?它不可能是一个函数,在当前的类型系统中不可能,并且引入新的语言级构造在任何标准下都是不值得的,特别是考虑到较大的元组是罕见的,而且很少是一个好主意(您听过“每一个新特性都从-100点开始”的说法吗?)。ghc的可能副本没有扩展,但有图书馆提供(见augustss的答案)。虽然这个答案没有错误,但它不是重点;参见下面Don Steward的回答我的冲动可能是说“-1迫使用户将元组大小包含为“sel”,特别是因为它总是紧跟在它从中选择的元组之前,”但当然,-1位于第位写入者,而不是用户。
cabal update
cabal install tuple
ghci

λ> import Data.Tuple.Select
λ> sel3 (0, "1", 2) --select the third element