函数take6错误中的非穷举模式?
问题描述:
所以我创造了这个功能,给我的 “N” 第一要素从列表中,“(B:BS);函数take6错误中的非穷举模式?
1 module Sexta where
2
3 take6::Int->[a]->[a]
4 take6 n (b:bs) = if n<=0 then []
5 else [b] ++ (take6 (n-1) bs)
的问题是,当我尝试:take6 2 []
,它表明:
*** Exception: sexta.hs:(4,1)-(6,15): Non-exhaustive patterns in function take6
我不为什么,因为当我尝试这手:
take6 2 []
= [] ++take6 1 []
= [] ++[]++take6 0 []
= [] ++[]++[]
= []
答
在程序中这样写:
take6 n (b:bs) = ...
但在这里,你这样使用一个模式(b:bs)
这是列表的“利弊”的构造。 cons构造函数的头部为b
,尾部为bs
。列表类型有两个构造函数:我们已经在这里讨论过的“cons”和空列表[]
。 Haskell抱怨说,它无法为第二个参数的空列表模式找到一个子句。所以你的功能需要用形状定义:
take6 n [] = ...
take6 n (b:bs) = ...
现在问题仍然是在这里做什么。无论什么样的,我们采取空单的情况下,我们不能发出任何元素了,所以你可能要返回空列表,因此:
take6 _ [] = []
而且你做确实n
之间的区别小于或等于零在这种情况下,结果是一个空列表:
take6 n (b:bs) | n <= 0 = []
但还存在n > 0
的情况。在这种情况下,我们确实需要在take6 (n-1) bs
之前加上b
。然而,一个更有效的方式来预先考虑,再次使用“缺点”构造记:
或全部:
take6 :: Int -> [a] -> [a]
take6 _ [] = []
take6 n (b:bs) | n <= 0 = []
| otherwise = b : take6 (n-1) bs
答
模式b:bs
不匹配空单需要有单独的情况下公顷ndle空列表。
答
您在检查n之前解构了列表,因此即使它为0,您也要求该列表不为空。您可以使用警卫来处理这种情况,但在列表太短的情况下,这无助于您。
是的,它可能更有效。但是,当GHC在启用优化的情况下运行时,它们最终应该是相同的。我没有检查过这个例子,但是有一些特殊的规则将文字列表排除为'build'形式,它应该与'(++)'中的'foldr'形式融合。在这种情况下,依靠这种优化是毫无意义的,但我认为使用'[a]'作为foldMap的monoid目标时更重要。 – dfeuer