2017-10-08 54 views
2

所以我创造了这个功能,给我的 “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 [] 
    = [] ++[]++[] 
    = [] 

回答

3

在程序中这样写:

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 
+0

是的,它可能更有效。但是,当GHC在启用优化的情况下运行时,它们最终应该是相同的。我没有检查过这个例子,但是有一些特殊的规则将文字列表排除为'build'形式,它应该与'(++)'中的'foldr'形式融合。在这种情况下,依靠这种优化是毫无意义的,但我认为使用'[a]'作为foldMap的monoid目标时更重要。 – dfeuer

2

模式b:bs不匹配空单需要有单独的情况下公顷ndle空列表。

2

您在检查n之前解构了列表,因此即使它为0,您也要求该列表不为空。您可以使用警卫来处理这种情况,但在列表太短的情况下,这无助于您。