如何处理我自己的`last`版本中的空列表?

时间:2015-03-07 09:56:07

标签: list haskell

我无法编译这个简单的Haskell函数。这是来自99个Haskell问题,其中一个应该实现last。我写了以下版本:

 myLast :: [a] -> a
 myLast []     = []       
 myLast (x:[]) = x          
 myLast (x:xs) = myLast(xs) 

但是,如果我将其加载到GHCi中,我会收到错误:

Couldn't match expected type `a' with actual type `[t0]'
  `a' is a rigid type variable bound by
      the type signature for myLast :: [a] -> a at problem1.hs:1:11
Relevant bindings include
  myLast :: [a] -> a (bound at problem1.hs:3:1)
In the expression: []
In an equation for `myLast': myLast [] = []
Failed, modules loaded: none.

告诉我

myLast[]    = [] 

是问题。

如果我删除它,它会被正确解释。但是如果我通过空列表

Prelude> myLast []

我得到了

> Non-exhaustive patterns in function myLast

这是有道理的,因为我没有匹配条件中的空列表。任何人都可以向我解释这个错误以及如何解决它吗?

2 个答案:

答案 0 :(得分:5)

如果您有一个空列表,则无法返回a,因为没有返回。您可以通过返回myLast而不是Maybe a来对a类型中的这种可能性进行编码。然后,如果列表为空,则可以返回Nothing

myLast :: a -> Maybe a
myLast [] = Nothing

如果您无法更改功能类型,则唯一的选择是引发错误:

myLast [] = error "Empty list"

答案 1 :(得分:2)

您的类型签名说

myLast :: [a] -> a

如果将列表传递给myList,它将返回列表中元素类型的单个元素。但是,你的定义是

myLast [] = []

如果你传递一个空列表,它会返回一个空列表。在签名中,您提到了一个元素,但在定义时您正在说一个列表。这就是Haskell抱怨这条线的原因。

但是当您删除该定义并使用空列表调用myLast时,它无法将输入与为myLast定义的任何模式匹配。这就是它失败的原因

Non-exhaustive patterns in function myLast

在这种特殊情况下,您没有有效的输入可供使用。所以,最好抛出一个错误,比如这个

myLast [] = error "Atleast one element should be there to find the last element"