Haskell:不使用(++)连接列表

时间:2013-10-01 00:18:00

标签: list haskell merge concatenation add

我正在尝试编写一个将两个列表组合在一起而不使用“分而治之”的函数。因此,我无法使用(++)

Prelude> let combineList (x:xs) (y:ys) = if null (y:ys)==True then x:xs else combineList (x:xs++[y]) (ys)

这就是我现在所拥有的,我得到"Non-exhaustive patterns in function combineList"。我意识到问题来自if null (y:ys)==True,因为这个函数有效 -

Prelude> let combineList (x:xs) (y:ys) = if ys==[] then x:xs++[y] else combineList (x:xs++[y]) (ys)

但是如果可能的话,我想摆脱输出中的++[y]

非常感谢对代码的更正。

2 个答案:

答案 0 :(得分:3)

(x:xs)与任何列表都不匹配。相反,它匹配具有头元素x和尾xs的列表。 (我猜你可以把它想象成匹配 cons 单元格。)null (x:xs)也不能是假的,因为任何(x:xs)都不是null,基本上按照定义。

"Non-exhaustive patterns in function"表示输入无法与函数的模式匹配。在这种情况下,两个参数都不能为null,因此如果其中一个为null,则匹配失败。

由于您显然是使用if s进行的,因此您需要匹配任何列表,因此该功能看起来像

combineList xs ys = if null xs then ys else head xs : combineList (tail xs) ys

然而,在haskell中执行此操作的更常用方法是分别与nil模式进行模式匹配:

cl [] ys = ys
cl (x:xs) ys = x : cl xs ys

(这相当于(++)的定义,但是以前缀形式:):

(++) :: [a] -> [a] -> [a]
(++) []     ys = ys
(++) (x:xs) ys = x : xs ++ ys
 -- or         = x : (++) xs ys

它也遵循 fold 模式:我们可以在第一个列表上累积consing,第二个列表用作初始尾部:

cl' xs ys = foldr (:) ys xs

这也允许我们无意义地编写函数(即以样式):

cl'' = flip (foldr (:))

答案 1 :(得分:1)

警告"Non-exhaustive patterns in function `combineList`"表示您的函数没有模式匹配数据类型的每个构造函数。 List类型包含两个构造函数(:)[];当您使用模式匹配时,编译器会假定您要匹配数据类型的每个构造函数。

以下是一种可能的解决方案:

combineList (x:xs) ys = if null xs then x : ys else x : combineList xs ys

在Haskell中,更好的方法是使用模式匹配。请注意,这也是(++)的实际定义:

combineList []     ys = ys 
combineList (x:xs) ys = x : combineList xs ys