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

List 如何处理我自己版本的“last”中的空列表?,list,haskell,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]'

我很难编译这个简单的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 []
我明白了


这很有意义,因为我在匹配条件中没有空列表。有人能给我解释一下这个错误以及如何修复它吗?

如果你有一个空列表,那么你就不能返回一个
a
,因为没有可以返回的。您可以通过返回一个
可能是一个
而不是
a
来将这种可能性编码为
myLast
类型。如果列表为空,则可以返回
Nothing

myLast :: a -> Maybe a
myLast [] = Nothing
如果无法更改函数的类型,则唯一的选项是引发错误:

myLast [] = error "Empty list"

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

myLast :: a -> Maybe a
myLast [] = Nothing
如果无法更改函数的类型,则唯一的选项是引发错误:

myLast [] = error "Empty list"

你的签名上写着

myLast :: [a] -> a
如果将列表传递给
myList
,它将返回列表中元素类型的单个元素。但是,你的定义是

myLast [] = []
如果您传递一个空列表,它将返回一个空列表。在签名中,您提到了单个元素,但在定义时,您说的是列表。这就是哈斯克尔抱怨这句台词的原因

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

函数myLast中的非穷举模式
在这种特殊情况下,您没有可处理的有效输入。所以,最好抛出一个错误,像这样

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

你的签名上写着

myLast :: [a] -> a
如果将列表传递给
myList
,它将返回列表中元素类型的单个元素。但是,你的定义是

myLast [] = []
如果您传递一个空列表,它将返回一个空列表。在签名中,您提到了单个元素,但在定义时,您说的是列表。这就是哈斯克尔抱怨这句台词的原因

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

函数myLast中的非穷举模式
在这种特殊情况下,您没有可处理的有效输入。所以,最好抛出一个错误,像这样

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

我想添加这样的内容:“毕竟,如何选择空列表的最后一个元素?如何选择空列表的任何元素?没有明智的选择。但是,您可以将函数的类型稍微更改为
myLast::[a]->可能是a
,然后返回
仅x
无任何内容
”@Zeta我来自Scala。这就更有意义了。我想添加一些类似的内容:“毕竟,如何选择空列表的最后一个元素?如何选择空列表的任何元素?没有明智的选择。但是,您可以将函数的类型稍微更改为
myLast::[a]->可能是一个
,或者返回
仅x
或者
“@Zeta我来自Scala背景。这就更有意义了。last实际上是一个非常糟糕的函数,它是局部函数,它对空列表没有正确的求值,因此唯一的选择是出错(隐式使用非穷举模式,或显式使用
错误“last对空列表不起作用”
稍好一点,但在大型程序中调试时仍然很糟糕)。这是你不应该使用的函数之一,比如
head
tail
。如果你需要一个安全的最后一个,我会建议你看看库中的所有选择与理智的类型。当然,对于一个无关紧要的练习来说!:)只是为了好玩,你能用
foldl
编写
myLast::[a]>可能是一个
,并且没有显式递归吗?最后一个函数实际上是一个非常糟糕的函数,它是局部的,它没有对空列表进行适当的计算,所以唯一的选择是出错(隐式使用非穷举模式或显式使用
错误)“last在空列表上不起作用”
这稍微好一点,但在大型程序中调试起来仍然很糟糕)。这是你不应该使用的函数之一,比如
head
tail
。如果你需要一个安全的last,我建议你在库中查找所有类型更为合理的选项。当然,对于一个不太重要的练习!:)只是为了好玩,你能写
myLast:[a]->可能是一个
使用
foldl
且没有显式递归的