为什么将“可能应用”的“纯”定义为“纯=正义”而忽略“无”?

时间:2018-10-27 10:45:09

标签: haskell applicative

source code of GHC.Base中,Applicative Maybe定义为:

instance Applicative Maybe where
    pure = Just
    ...

我想知道为什么纯正的定义忽略了Nothing

根据这个定义,我希望

pure Nothing应该减少到Just Nothing,因为pure = Just

Prelude> Just Nothing
Just Nothing

而不是实际上:

Prelude> pure Nothing
Nothing

为什么这是魔术?我怎么了谢谢!

2 个答案:

答案 0 :(得分:5)

它不会忽略Nothing,但是如果运行<Applicative函数,则需要为指定哪个 pure我们使用-XTypeApplications运行它,我们可以指定Applicative的类型,然后获得:

$ ghci -XTypeApplications
GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
Prelude> pure @Maybe Nothing
Just Nothing

如果未指定类型,则解释器将“默认”为某个Applicative(在这种情况下为IO)变体,因此这意味着它将返回该值,并且解释器的标准行为是在IO shell中打印值“ wrapped”。

Applicative占用pure = Just的原因是,它必须与Functor实例一致。此仿函数实例定义为:

instance Functor Maybe where
    fmap f (Just x) = Just (f x)
    fmap _ Nothing = Nothing

现在需要满足的法律之一是:

fmap f x = pure f <*> x

因此,如果我们定义pure _ = Nothing,则意味着fmap f x = Nothing <*> x,这意味着我们“丢失了有关f的信息”。结果,唯一合理的解决方案可能是fmap总是返回Nothing,但这作为函子没有多大意义。此外,它还会违反函子级的另一个约束,即fmap id x应该始终返回x

答案 1 :(得分:4)

pure已超载。单独输入pure Nothing时,您无需指定要调用的pure版本。它本身具有类型

pure Nothing :: Applicative f => f (Maybe a)

如果您明确地说想要Maybe (Maybe a),您将得到期望的结果:

ghci> pure Nothing :: Maybe (Maybe a)
Just Nothing

但是,当您在GHCi中键入pure Nothing时,它实际上选择制作一个IO (Maybe a)。这是因为GHCi尝试运行它可以执行的任何IO操作。当它执行动作pure Nothing :: IO (Maybe a)时,您将返回Nothing。您还可以提供类型签名:

ghci> pure Nothing :: IO (Maybe a)
Nothing

也就是说,您从未调用过pure = Just的{​​{1}}版本。您调用了另一个函数,也称为pure。这就是为什么您会有一些有趣的行为的原因。