2

所以我创建了这个函数,给我列表中的“n”个第一个元素,“(b:bs);

 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 []
   = [] ++[]++[]
   = []
4

3 回答 3

3

在您的程序中,您编写:

take6 n (b:bs) = ...

但是在这里,您因此使用了一个模式(b:bs),它是列表的“cons”构造函数。cons 构造函数接受一个 headb和一个 tail bs。然而,列表类型有两个构造函数:我们已经在这里讨论过的“缺点”和空列表[]。Haskell 抱怨它找不到第二个参数的空列表模式的子句。所以你的函数需要用一个形状来定义:

take6 n [] = ...
take6 n (b:bs) = ...

现在的问题仍然是在这里做什么。无论我们在空列表的情况下采取什么措施,我们都不能再发出任何元素,所以您可能想要返回空列表,所以:

take6 _ [] = []

此外,您确实区分了n小于或等于零,在这种情况下,结果是一个空列表:

take6 n (b:bs) | n <= 0 = []

但也有一种情况n > 0。在这种情况下,我们确实希望btake6 (n-1) bs. 但是请注意,一种更有效的前置方法是再次使用“cons”构造函数:

               | otherwise = b : take6 (n-1) bs

或全部:

take6 :: Int -> [a] -> [a]
take6 _ [] = []
take6 n (b:bs) | n <= 0 = []
               | otherwise = b : take6 (n-1) bs
于 2017-10-08T20:20:29.023 回答
2

该模式b:bs与空列表不匹配。您需要一个单独的案例来处理空列表。

于 2017-10-08T20:14:41.627 回答
2

你在检查n之前解构列表,所以即使它是 0 你也要求列表是非空的。您可以使用警卫来处理这种情况,但是在列表太短的情况下这无济于事。

于 2017-10-08T20:14:56.930 回答