带字符串的模式 x:xs

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。

use*_*643 5

首先,如果你检查(++)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)

这按预期工作。