我在“为了好大学而学习你的哈斯克尔”一书的第118页。
写在那里:
ghci> :t Nothing
Nothing :: Maybe a
这是我的问题:
如果我理解正确,Nothing
是一个值,只有具体类型可以有值,但Maybe a
不是具体类型。那么它如何具有值Nothing
?
这本书还说:
请注意,Nothing的类型可能是a。它的类型是多态的。
多态类型是什么意思?我该怎么理解这个?这与仅具体类型可以具有价值的规则不矛盾吗?
编辑:
从本书的PDF版本:
如果不采用任何类型参数,我们说类型是具体的 在所有(如Int或Bool),或者如果它采用类型参数,他们是 所有人都填满了(比如Maybe Char)。如果你有一些价值,它的类型是 总是具体的类型。
答案 0 :(得分:13)
这并不矛盾。 Nothing
是一个值,其具体类型可能是Maybe a
的任何可能的实例化。
否则说,类型Maybe a
的值继续具有具体类型Maybe Int
,Maybe String
,Maybe Whatever
,特别是Nothing
能够由每个人输入,具体取决于具体情况。这是因为它的构造函数(再次称为Nothing :: Maybe a
)不接受任何参数,因此可以按原样调用它来生成类型Maybe a
的值。如果您愿意,我们将根据具体类型提供一种。
如果没有上下文,ghci当然会为你提供Nothing
可以推断出的最一般的类型,即Maybe a
,但它不是它的具体类型。这将取决于您将使用的Nothing
个人表达式。例如:
ghci> Nothing
Nothing
it :: Maybe a
这是您可能输入的内容,或者类似的内容。没有进一步的上下文,因此Nothing
不会使用具体类型进行输入。
ghci> Nothing :: Maybe Int
Nothing
it :: Maybe Int
在这里,我强制它假设具体类型Maybe Int
。
ghci> 1 + fromMaybe 2 Nothing
3
it :: Integer
如果我将其与一个整数混合使用(fromMaybe :: a -> Maybe a -> a
采用默认值和Maybe a
并返回Just
中的值或Nothing
的默认值),然后Nothing
将被系统输入为Maybe Integer
,因为您希望从中提取一个整数。没有,所以在这种情况下,我们将1与默认值2相加。
ghci> 1 + fromMaybe 2 (Nothing :: Maybe Integer)
3
it :: Integer
同样在这里,仔细检查。我们强迫Nothing
拥有我们之前在同一个表达式中所具有的具体类型。
ghci> 1 + fromMaybe 2 (Nothing :: Maybe Char)
<interactive>:1:15:
No instance for (Num Char)
arising from the literal `2'
Possible fix: add an instance declaration for (Num Char)
In the first argument of `fromMaybe', namely `2'
In the second argument of `(+)', namely
`fromMaybe 2 (Nothing :: Maybe Char)'
In the expression: 1 + fromMaybe 2 (Nothing :: Maybe Char)
要进行三重检查,如果我们强制它假设另一个具体类型,你会看到它的值将完全不同,导致类型错误(与C不同,在Haskell Char
中不起作用数)。
答案 1 :(得分:5)
这与规则不矛盾,唯一的具体类型可以有价值吗?
由于函数是Haskell中的第一类值,因此这个声称的规则意味着诸如map
和foldr
之类的多态函数将无法实现。
事实上,Haskell中有很多多态非函数值,例如
1 :: Num a => a
Nothing :: Maybe a
[] :: [a]
Left 1 :: Num a => Either a b
等。这些值适用于a
(和b
)的每个实例化。
答案 2 :(得分:3)
从某种意义上说,你是对的。没有forall a.Maybe a
类型的值。你构造的每个Maybe值实际上都有一些明确的类型Maybe tau
,其中tau
可能是已知的,但是它是一些明确的类型。
符号Nothing :: forall a.Maybe a
只是告诉我们,每当我们使用表达式Nothing
时,它都会构造一个预期Maybe
类型的值。
答案 3 :(得分:1)
Maybe类型有两个构造函数:Nothing和Just a,其中a是一个类型变量。没有什么本身不会决定(约束)类型,但在任何合理的上下文中你都会发现类似的东西(我并不认为它在语法上是正确的Haskell,而是10年前我会写的):
if (foo == 5)
then Nothing
else Just 5
然后类型推断会告诉你(假设5是这个类型为Int的代码片段'foo'的参数)foo有类型:
foo :: Int -> Maybe Int
但正如之前的海报所指出的,也许a是一种非常好的类型。您将找到与[]相同的非问题,即带有[]的列表类型(空列表的构造函数)。
答案 4 :(得分:0)