繁体   English   中英

将非空列表传递给函数

[英]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 xsxs[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM