我是Haskell世界的新手。我正在阅读在线http://learnyouahaskell.com,但我无法理解有关模式匹配部分的细节。我写了这些函数
myFunc' (firstLetter:_) = firstLetter -- returns firstLetter of given string
但是,如果我做那样的事情
myFunc' (firstLetter:_) = "Hello" ++firstLetter
当我调用此函数时给我以下错误
Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [[Char]]
Actual type: [Char]
但如果我修改这个功能
myFunc' (firstLetter:_) = "Hello" ++ [firstLetter]
当我调用此函数时,它工作正常。我想知道为什么在其他情况下我需要括号。什么是第一封信。
答案 0 :(得分:4)
"Hello ++ firstLetter
有类型:
[Char] ++ Char
如您所见,这是不可能的。您无法将Char
添加到[Char]
,它们是不同的类型!
但是做了
[firstLetter]
您正在创建一个包含1个元素firstLetter
的列表。由于firstLetter
是Char
,您将获得Char
的列表,即列表的类型为[Char]
。
允许添加2个相同类型的列表,这就是它在第二种情况下有效的原因。
答案 1 :(得分:4)
首先,如果你在ghci中检查(++)
的类型,你会得到:
Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
这意味着它需要两个作为参数的列表。
同样,让我们看看(:)
做了什么:
Prelude> :t (:)
(:) :: a -> [a] -> [a]
所以(:)
的第一个参数根本不需要是一个列表。如果我们修复a == Char
,我们实际上会获得(:) :: Char -> String -> String
。
我们可以定义一个函数headStr
(召回String == [Char]
):
headStr :: String -> Char
headStr (x:_) = x
headStr _ = error "Empty string!"
请注意,由于(:)
x :: Char
的类型{。}}。
另一方面,如果我们尝试定义:
hello :: String -> String
hello (x:_) = "Hello" ++ x
hello _ = error "Empty string!"
它不会进行类型检查,因为在非错误情况下我们得到[Char] ++ Char
。正如ghci有用地告诉我们的那样,(++)
的第二个参数必须始终是一个列表,在这种情况下,因为第一个参数是[Char]
,它也必须是[Char]
。
正如您自己注意到的那样,可以通过将x
包装在列表中来解决此问题:
hello' :: String -> String
hello' (x:_) = "Hello" ++ [x]
hello' _ = error "Empty string!"
这可以按预期工作。