Haskell 将非空列表传递给函数
我编写了这个小函数来检索列表的尾部:Haskell 将非空列表传递给函数,haskell,parameter-passing,tail,Haskell,Parameter Passing,Tail,我编写了这个小函数来检索列表的尾部: let getTail l = if length l > 0 then tail l else "empty list" 将[]传递到getTail会返回空列表,但传递[1,2,3]会产生以下错误: <interactive>:1:14: No instance for (Num Char) arising from the literal `3' Possible fix: add an instance declaration
let getTail l = if length l > 0 then tail l else "empty list"
将[]
传递到getTail
会返回空列表
,但传递[1,2,3]
会产生以下错误:
<interactive>:1:14:
No instance for (Num Char)
arising from the literal `3'
Possible fix: add an instance declaration for (Num Char)
In the expression: 3
In the first argument of `getTail', namely `[1, 2, 3]'
In the expression: getTail [1, 2, 3]
:1:14:
没有(Num Char)的实例
源于字面上的'3'
可能的修复方法:添加(Num Char)的实例声明
在表达式中:3
在“getTail”的第一个参数中,即“[1,2,3]”
在表达式中:getTail[1,2,3]
我不明白那个错误是什么意思。有什么问题?使用GHCi 7.0.4
Prelude> let getTail l = if length l > 0 then tail l else "empty list"
您没有为getTail
提供类型签名,因此会推断出一个类型签名
Prelude> :t getTail
getTail :: [Char] -> [Char]
:t
提供GHCi中任何内容的类型。这是非常有用的。类型签名说明了很多关于Haskell中函数的信息
这可能不是你的意思。为什么它只适用于[Char]
,(或者相当于String
),而不适用于任何列表
原因如下:
一个函数只能有一个返回类型。由于在列表为空时返回“空列表”
,因此返回类型必须为字符串。碰巧的是,tail xs
的返回类型,xs
是一个[Char]
也是一个字符串
,这就是为什么在首次定义函数时不会出现错误的原因。因此,您的函数必须是[Char]->[Char]
您试图用参数[1,2,3]
调用它,该参数的类型为Num a=>a
。GHC告诉你“一个Char
没有Num的实例”,或者“我不能把一个数字转换成一个Char”。这涉及到类型类,如果你还不理解它们,那没关系,因为你仍然会在尝试getTail([1,2,3]:[Int])
时出错。您试图将Int
s列表传递给一个函数,该函数接受Char
s列表
我建议通读哈斯克尔类型系统。应该是[]
而不是“空列表”
(你是混合类型)
让我们考虑一下getTail
函数的类型。最初,我们可以想象l
是任何列表。但是,返回类型必须是字符串
,因为有时会返回“空列表”
。由于这是if语句的一部分,您可能还返回tail l
,这意味着l
必须是字符串
因此,您的getTail
函数具有类型String->String
当您使用[1,2,3]
调用getTail
时,它需要一个字符串,它只是一个[Char]
。请记住,数字文字是重载的:[1,2,3]
相当于调用[fromInteger 1、fromInteger 2、fromInteger 3]
。因此,给定这个列表,Haskell试图从字符中获取一个数字。由于Char
s不是Num
类的一部分,因此此操作将失败,并导致错误
一个好的解决方案是返回一个Maybe
类型,并为错误提供Nothing
,而不是返回“空列表”
。因此,将函数重写为:
let getTail l = if length l > 0 then Just (tail l) else Nothing
现在它的类型是[a]->可能是[a]
。使用此选项将迫使任何使用您的函数的人在能够使用结果之前检查getTail
是否成功
另一个选项是返回[]
以代替“空列表”。在这种情况下,getTail
函数的工作方式与drop 1
完全相同 我不认为他在GHCi中这一事实很重要:这是任何地方都可以推断出来的类型。我已经读过了:)我想我写函数时没有理解函数类型(我一直读到tail
,认为是时候组合编写使用内置函数的函数了。因此,玩具函数)
let getTail l = if length l > 0 then Just (tail l) else Nothing