我正在尝试编写一个将两个列表组合在一起而不使用“分而治之”的函数。因此,我无法使用(++)
。
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]
。
非常感谢对代码的更正。
答案 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
这也允许我们无意义地编写函数(即以pointfree样式):
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