谁能解释为什么“Anna”++ [' '] 在 Haskell 中有效,但在 1 ++ [' '] 中无效?

noe*_*ndo 3 string haskell list build

我试图构建一个字符串列表,但我不明白为什么 String ++ [' '] 有效。如果我尝试处理数字,例如 1 ++ [' '],它不起作用。

我做了:“Anna”++ [' '] 有效,但 1 ++ [' '] 不行。是什么原因?

Jon*_*rdy 6

在 GHCi 中,您可以使用该:info命令获取有关如何定义名称的信息。:set prompt "\xce\xbb "(此外,我已通过添加到我的配置文件中将提示设置为 lambda .ghci。)

\n
\xce\xbb :info String\ntype String :: Type\ntype String = [Char]\n    -- Defined in \xe2\x80\x98GHC.Base\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

String[Char]是Unicode 字符列表的类型同义词。单引号表示一个字符,当然你可以列出它们。

\n
\xce\xbb :type ' '\n' ' :: Char\n\n\xce\xbb :type [' ']\n[' '] :: [Char]\n
Run Code Online (Sandbox Code Playgroud)\n

并且双引号形成String.

\n
\xce\xbb :type " "\n" " :: String\n
Run Code Online (Sandbox Code Playgroud)\n

由于这两种类型相等,因此有多种表达等效值的方法。

\n
\xce\xbb " " == [' ']\nTrue\n\n\xce\xbb "abc" == ['a', 'b', 'c']\nTrue\n\n\xce\xbb "abc" == 'a' : "bc"\nTrue\n\n\xce\xbb "abc" == 'a' : 'b' : 'c' : []\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n

由于String是一个列表,因此您可以对其进行列表操作。

\n
\xce\xbb :info ++\n(++) :: forall a. [a] -> [a] -> [a]     -- Defined in \xe2\x80\x98GHC.Base\xe2\x80\x99\ninfixr 5 ++\n\n\xce\xbb ("abc" ++ "def") == (['a', 'b', 'c'] ++ ['d', 'e', 'f'])\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n

然而,1 ++ [' ']\xe2\x80\x99 不起作用,因为它需要1类型[Char]。数字文字通过类型类重载Num,因此这意味着编译器会查找instance Num [Char]. 由于该实例未定义\xe2\x80\x99t,因此会引发错误。

\n
\xce\xbb :type 1 ++ [' ']\n\n<interactive>:1:1: error:\n    \xe2\x80\xa2 No instance for (Num [Char]) arising from the literal \xe2\x80\x981\xe2\x80\x99\n    \xe2\x80\xa2 In the first argument of \xe2\x80\x98(++)\xe2\x80\x99, namely \xe2\x80\x981\xe2\x80\x99\n      In the expression: 1 ++ [' ']\n
Run Code Online (Sandbox Code Playgroud)\n

虽然在技术上可以定义这样一个实例\xe2\x80\x94,或者实际上为任何Applicative未包含在标准库中的\xe2\x80\x94it\xe2\x80\x99s定义一个通用实例,因为它很容易被无意中使用;如果它遵循 的规律Num,那么它的行为方式可能会令人惊讶String

\n