2

我正在阅读《Learn you a Haskell for great good》和第 40 页 - 作为模式。

我将示例稍微更改为:

firstLetter :: String -> String
firstLetter "" = "Empty string, oops"
firstLetter all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x] ++ " otherbit " ++ xs

然后可以这样使用:

*Main> firstLetter "Qwerty"
"The first letter of Qwerty is Q otherbit werty"

但是我对 [x] 和 x 之间的区别以及为什么在上面的示例中必须使用 [x] 感到困惑。

例如,如果我更改为

firstLetter :: String -> String
firstLetter "" = "Empty string, oops"
firstLetter all@(x:xs) = "The first letter of " ++ all ++ " is " ++ x ++ " otherbit " ++ xs

我得到错误:

Couldn't match expected type `[Char]' with actual type `Char'
In the first argument of `(++)', namely `x'
In the second argument of `(++)', namely `x ++ " otherbit " ++ xs'
In the second argument of `(++)', namely
  `" is " ++ x ++ " otherbit " ++ xs'

我可以xs用来打印"werty",但必须用来[x]打印“Q”。这是为什么?

是什么[x]意思?

(x:xs) 中,:仅分隔每个元素,x第一个元素也是如此。为什么我不能使用 打印x

xs是什么类型的?值列表?那么这是否意味着x是一个元素并且xs必须是列表类型?

4

4 回答 4

6

++用于连接列表:

(++) :: [a] -> [a] -> [a]  

[x]是列表,x不是列表。

firstLetter (x:xs)是模式匹配的一个例子。

(:) :: a -> [a] -> [a]  

此运算符在列表之前添加元素。
因此 type ofx是元素,type ofxs是元素列表。在 Haskell 中,在列表名称中添加后缀 's' 是很常见的。

于 2013-04-03T09:04:42.783 回答
5

String定义为type String = [Char]

"Qwerty"['Q', 'w', 'e', 'r', 't', 'y'];的简写 这又是'Q' : 'w' : 'e' : 'r' : 't' : 'y' : [].

因此,当您与 匹配x : xs"Qwerty",您会得到x = 'Q'xs = "werty"

x     : xs
('Q') : ('w' : 'e' : 'r' : 't' : 'y' : [])

注意:x = 'Q',不是x = "Q"'Q'是 aChar并且"Q"是 a String(即 a [Char])。但是如果你有'Q'并且你想要"Q",你可以写['Q'],因为"Q"它只是 的简写['Q']

所以简短的回答是你必须这样做才能使类型匹配。[x]是一个长度为 1 的列表,它的单个元素是x.


在这:

firstLetter all@(x:xs)
    = "The first letter of " ++ all ++ " is " ++ x ++ " otherbit " ++ xs

您正在构建要使用打印的字符串++。有类型

(++) :: [a] -> [a] -> [a]

++需要两个列表,并给你一个列表。

x不是一个列表。所以你得到一个类型错误。

相反,您使用

"The first letter of " ++ all ++ " is " ++ [x] ++ " otherbit " ++ xs

现在所有参数++都是列表,并且所有类型都匹配。

但你可以改为使用

"The first letter of " ++ all ++ " is " ++ x : " otherbit " ++ xs

因为类型:是由

(:) :: a -> [a] -> [a]
于 2013-04-03T09:02:36.937 回答
3

[x] 表示“仅包含元素 x 的列表”。

由于 Haskell 中的 String 是一个字符列表,如果 x 是字符 'Q' 那么 [x] 是字符串 "Q"。++ 运算符期望接收两个字符串作为参数,因此您不能只给它一个字符。

这就是编译器告诉你的:Couldn't match expected type `[Char]' with actual type `Char'意味着编译器期待一个 [Char] 类型的参数(它是一个字符列表,与 String 相同)但你传递给它一个 Char。

于 2013-04-03T09:03:58.357 回答
1

还可以注意到,在许多编程语言中,连接运算符要么被重载,因此根据两边的类型有几种实现,或者参数将被强制转换为字符串。在 Haskell 中情况并非如此。

于 2013-04-03T14:38:27.003 回答