我目前正在与赫顿教授的“在Haskell中编程”一起研究Haskell,我发现Maybe作为Applicative类的实例的定义有些奇怪。
在GHC.Base
中,实例Applicative Maybe
的定义如下:
instance Applicative Maybe where
pure = Just
Just f <*> m = fmap f m
Nothing <*> _m = Nothing
将Nothing <\*> _
的值定义为Nothing
的那行让我感到困扰。 Nothing
的类型为Maybe a
,其中运算符<*>
实际上需要f (a -> b)
(在这种情况下为Maybe (a -> b)
)作为其第一个参数的类型。因此,这是类型不匹配,Haskell应该抱怨。但是,这被接受为默认定义,因此Haskell不会在我认为应该的位置抱怨它。
我想念什么?
答案 0 :(得分:11)
<*>
中的a
是一个类型变量,根本可以是任何类型!例如,Maybe a
的类型可以为Nothing
或Maybe Int
或Maybe [x]
。
不要为变量名Maybe (p -> q)
在两个地方使用而感到困惑。 a
类型的a
与Nothing
类型的a
是完全不同的变量,并且恰好具有相同的名称!
(这与您写过<*>
然后写其他地方f x = x + 5
完全一样。在两个地方都使用g x = "Hello, " ++ x
并不重要,因为它们的作用域不同。与此类型中的x
相同。作用域不同,因此它们是不同的变量。)
答案 1 :(得分:4)
让我们通过重新标记类型变量来使事情更清楚:
Nothing :: Maybe x
类型Maybe x
与Maybe (a -> b)
和x ~ (a -> b)
统一。也就是说,Nothing
是可用作 any Maybe a
的{{1}}的值,包括函数类型。因此,这里是a
的合法左手参数。