Can*_*Can 1 haskell pattern-matching
我在 Haskell 世界中很新。我正在阅读在线http://learnyouahaskell.com,但我无法理解有关模式匹配部分的一个小细节。我已经写了那些函数
myFunc' (firstLetter:_) = firstLetter -- returns firstLetter of given string
Run Code Online (Sandbox Code Playgroud)
但是,如果我这样做
myFunc' (firstLetter:_) = "Hello" ++firstLetter
Run Code Online (Sandbox Code Playgroud)
调用此函数时出现以下错误
Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [[Char]]
Actual type: [Char]
Run Code Online (Sandbox Code Playgroud)
但是如果我像这样修改函数
myFunc' (firstLetter:_) = "Hello" ++ [firstLetter]
Run Code Online (Sandbox Code Playgroud)
当我调用这个函数时效果很好。我想知道为什么在其他情况下我需要括号。什么实际上是firstLetter。
首先,如果你检查(++)ghci 中的类型,你会得到:
Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)
这意味着它需要两个 a 列表作为参数。
同样,让我们看看有什么(:)作用:
Prelude> :t (:)
(:) :: a -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)
所以第一个参数(:)根本不需要是一个列表。如果我们修复a == Char我们实际上得到(:) :: Char -> String -> String.
我们可以定义一个函数headStr(recall String == [Char]):
headStr :: String -> Char
headStr (x:_) = x
headStr _ = error "Empty string!"
Run Code Online (Sandbox Code Playgroud)
请注意,由于(:)在这种情况下的类型x :: Char。
另一方面,如果我们尝试定义:
hello :: String -> String
hello (x:_) = "Hello" ++ x
hello _ = error "Empty string!"
Run Code Online (Sandbox Code Playgroud)
它不会进行类型检查,因为在非错误情况下我们会得到[Char] ++ Char. 正如 ghci 有用地告诉我们的那样, to 的第二个参数(++)必须始终是一个列表,在这种情况下,因为第一个参数是[Char]它也必须是[Char]。
正如您自己注意到的,这可以通过包装x在列表中来解决:
hello' :: String -> String
hello' (x:_) = "Hello" ++ [x]
hello' _ = error "Empty string!"
Run Code Online (Sandbox Code Playgroud)
这按预期工作。