[英]Passing a non-empty list to a function
我写了这个小函数来检索列表的尾部:
let getTail l = if length l > 0 then tail l else "empty list"
传递[]
到getTail
返回empty list
但传递[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]
我无法理解那个错误意味着什么。 问题是什么? 使用GHCi 7.0.4
让我们考虑一下getTail
函数的类型。 最初,我们可以想象l
是任何列表。 但是,返回类型必须是String
因为有时会返回"empty list"
。 由于这是if语句的一部分,你也可能返回tail l
,这意味着l
必须是一个String
。
所以你的getTail
函数有String -> String
类型。
当你用[1,2,3]
调用getTail
时,它需要一个String
,它只是一个[Char]
。 请记住,数字文字是重载的: [1,2,3]
相当于调用[fromInteger 1, fromInteger 2, fromInteger 3]
。 因此,鉴于此列表,Haskell正试图从Char
获取一个数字。 由于Char
不属于Num
类,因此会失败,从而导致错误。
一个好的解决方案是返回一个Maybe
类型并为错误提供Nothing
而不是返回"empty list"
。 所以重写你的功能:
let getTail l = if length l > 0 then Just (tail l) else Nothing
现在它的类型是[a] -> Maybe [a]
。 使用此方法将强制任何使用您的函数的人在能够使用结果之前检查getTail
是否成功。
另一种选择是返回[]
代替“空列表”。 在这种情况下, getTail
函数的工作方式与drop 1
完全相同。
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
)上工作,而不能在任何列表上工作?
原因如下:
一个函数只能有一个返回类型。 由于在列表为空时返回"empty list"
,因此返回类型必须为String
。 tail xs
, xs
为[Char]
的tail xs
的返回类型也是一个String
,这就是为什么在第一次定义函数时没有出错的原因。 因此,您的功能必须是[Char] -> [Char]
。
你试图用参数[1, 2, 3]
来调用它,它的类型为Num a => a
。 GHC告诉你“A Char
没有Num的实例”,或者“我不能把数字变成Char。” 这涉及类型类 - 如果你还不理解那些,那也没关系,因为你仍然会得到你试过getTail ([1, 2, 3] :: [Int])
。 您正在尝试将Int
列表传递给一个获取Char
列表的函数。
我建议通过LYAH阅读以了解Haskell类型系统。
应该是[]
而不是"empty list"
(你是混合类型)
Prelude> let getTail l = if length l > 0 then tail l else []
Prelude> getTail [1, 2, 3]
[2,3]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.