我跟随现实世界的哈克尔,第2章有一个练习.
我的解决方案是
lastButOne xs = if null xs || null (tail xs)
then []
else if null (tail (tail xs))
then head xs
else lastButOne (tail xs)
Run Code Online (Sandbox Code Playgroud)
但除了[]之外它不起作用,并产生这样的错误.
*Main> lastButOne []
[]
*Main> lastButOne [1, 2]
<interactive>:5:13:
No instance for (Num [a0]) arising from the literal `1'
Possible fix: add an instance declaration for (Num [a0])
In the expression: 1
In the first argument of `lastButOne', namely `[1, 2]'
In the expression: lastButOne [1, 2]
Run Code Online (Sandbox Code Playgroud)
我是一个相当新手,不明白这些神秘的错误信息.有任何想法吗?
这是一个类型问题.如果您使用GHCi,请将此功能加载到其中并使用
:t lastButOne
Run Code Online (Sandbox Code Playgroud)
看它的类型,这是
lastButOne :: [[a]] -> [a]
Run Code Online (Sandbox Code Playgroud)
这是因为if需要在then和else分支上使用相同的类型,并且因为你[]在then分支中返回一个,Haskell认为你总是试图返回一个列表,并且因为你head xs在else分支上返回,它认为你是编写函数适用于列表列表.
但是,[1, 2]不是列表列表,所以GHC向你大吼大叫关于类型不匹配错误.
另请注意,如果您明确写出类型定义,则无法编译:
lastButOne :: [a] -> a
lastButOne xs = if null xs || null (tail xs)
then []
else if null (tail (tail xs))
then head xs
else lastButOne (tail xs)
Run Code Online (Sandbox Code Playgroud)
GHCi会给你一个错误:
Couldn't match type `a' with `[a0]'
`a' is a rigid type variable bound by
the type signature for lastButOne :: [a] -> a at k.hs:2:1
In the expression: []
In the expression:
if null xs || null (tail xs) then
[]
else
if null (tail (tail xs)) then head xs else lastButOne (tail xs)
In an equation for `lastButOne':
lastButOne xs
= if null xs || null (tail xs) then
[]
else
if null (tail (tail xs)) then head xs else lastButOne (tail xs)
Run Code Online (Sandbox Code Playgroud)