今天我开始学习Haskell。我对函数式语言有点陌生,而且我非常喜欢 Haskell。
然而,我有一个关于它的设计的问题困扰着我:从我到目前为止的理解来看,访问列表后面的元素似乎比访问前面的元素要复杂得多(类似于xs:x
where xs::[a]
and x::a
似乎不可能)。
(根据我的理解)可以将一个列表附加到另一个列表(xs++[a]
),但在运行时会花费更多(需要遍历整个列表)并且不能用于模式匹配。
为什么 Haskell 缺少这样的操作?
列表数据类型
data [a] = [] | a : [a]
定义如上。您只能匹配两种模式:[]
and x : xs
, where x
是头部和xs
是尾巴。
添加到列表前面
a = 1 : 2 : []
b = 0 : a
(:) <-- b
/ \
0 (:) <-- a
/ \
1 (:)
/ \
2 []
只需添加一个新的 cons 单元并重用原始列表作为尾部。
但是,请记住 Haskell 数据结构是不可变的。追加到列表的尾部
a = 1 : 2 : []
b = a ++ [3]
(:) <-- a (:) <-- b
/ \ / \
1 (:) 1 (:)
/ \ / \
2 [] 2 (:)
/ \
3 []
需要构建一个全新的列表,因为原始结构的任何部分都不能重复使用。
事实上,考虑
a = 0 : a
b = 0 : [ x+1 | x <- b ]
(:) <-- a (:) <-- b
/ \ / \
0 (:) <-- a 0 (:) <-- [ x+1 | x <- b ]
/ \ / \
0 (:) <-- a 1 (:) <-- [ x+1 | x <- [ x+1 | x <- b ] ]
... ...
您将如何获取列表的最后一个元素,或附加到末尾?
还有其他数据结构,例如dequeue http://hackage.haskell.org/package/dequeue更适合从正面和背面进行访问。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)