我不明白为什么当我查看类型时,例如:a = (1, 2)
我得到
a :: (Num a, Num b) => (a, b)
Run Code Online (Sandbox Code Playgroud)
相反,如果我查看以下类型:b = ('a', 'b')我得到
b :: (Char, Char)
Run Code Online (Sandbox Code Playgroud)
而不是类似的东西:
b :: (Char a, Char b) => (a, b)
Run Code Online (Sandbox Code Playgroud)
Haskell 有两种类型的文字:单态和多态。(虽然这样说可能更准确,但文字可以计算为单态或多态类型的值。)
\n'c'是单态文字的一个例子;它是单一类型的值,即Char.
> :t 'c'\n'c' :: Char\nRun Code Online (Sandbox Code Playgroud)\n1另一方面,是一个多态文字。它可以是具有实例的任何类型的值Num。
> :t 1\n1 :: Num p => p\n> :t 1 :: Int\n1 :: Int :: Int\n> > :t 1 :: Char\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 expression: 1 :: Char\nRun Code Online (Sandbox Code Playgroud)\n其他多态文字包括
\n浮点文字
\n> :t 3.4\n3.4 :: Fractional p => p\nRun Code Online (Sandbox Code Playgroud)\nOverloadedStrings启用扩展时的字符串文字。
> :t "foo"\n "foo" :: [Char]\n > :set -XOverloadedStrings\n > :t "foo"\n "foo" :: Data.String.IsString p => p\nRun Code Online (Sandbox Code Playgroud)\nOverloadedLists启用扩展时列出文字。
> :t ['a', 'b']\n['a', 'b'] :: [Char]\n> :set -XOverloadedLists\n> :t ['a', 'b']\n['a', 'b'] :: (GHC.Exts.IsList l, GHC.Exts.Item l ~ Char) => l\nRun Code Online (Sandbox Code Playgroud)\n数据构造函数Nothing(如果您想将无效构造函数视为文字)
> :t Nothing\nNothing :: Maybe a\nRun Code Online (Sandbox Code Playgroud)\nNothing例如,可以是 、 等类型的Maybe Int值Maybe Char。
Num是一个类型类,它是一组类型,这看起来有点类似于 Java/C#/...中的接口。作为Num类型类成员的类型需要实现一组特定的功能,就像在 Java 中一样实现接口的类型应该实现某些方法。Char另一方面,A是类型,而不是类型类。
如果您编写整数文字,它可以是该类型类成员的任何类型Num,因为该类型类有一个函数,fromInteger :: Num a => Integer -> a然后调用该函数将整数文字转换为该数字类型。
'a'如果您像另一方面一样编写 char 文字,那么唯一可以解析的类型是Char.
对于字符串文字,您可以使用OverloadedStrings扩展名,在这种情况下,字符串文字可以采用属于IsStringtypeclass成员的任何类型。