GHC 7.10.x迁移:为什么不能在实例中写一个“pure = return”Applicative?

时间:2016-03-02 09:05:18

标签: haskell ghc

我正在阅读一篇关于GHC 7.10.x Migration的文章。有一些修复错误的建议。

  

GHC说No instance for (Applicative ...)

     

如果GHC抱怨

     

Foo.hs:7:10:       没有实例声明的超类引起的(Applicative Foo)实例       在'Monad Foo'的实例声明中,修复此错误的一种简单方法是定义Applicative(可能还有Functor)   实例:实例Functor Foo在哪里           fmap = liftM            - 或者:            - fmap = m>> = pure。 ˚F

instance Applicative Foo where
    -- NB: DO NOT USE `pure = return`
    pure  = {- move the definition of `return` from the `Monad` instance here -}

    (<*>) = ap  {- defined in Control.Monad -}
    -- or alternatively:
    --  f1 <*> f2 = f1 >>= \v1 -> f2 >>= (pure . v1)

    -- NB: DO NOT USE `(*>) = (>>)`
    (*>) = {- move the definition of `>>` from the `Monad` instance here -}

instance Monad Foo where
    return = pure {- definition moved to `Applicative(pure)` -}

    (>>) = (*>) {- definition moved to `Applicative((*>))` -}

    {- ...retain other previous definitions... -}

有NB:DO NOT USE `pure = return`DO NOT USE `(*>) = (>>)。为什么不能使用它?

P.S。我试图使用它,它已被编译。

1 个答案:

答案 0 :(得分:7)

正如@WillSewell在评论中暗示的那样,base-4.8.0.0现在return类型类Monad中有一个默认实现:

class Applicative m => Monad m where
    return      :: a -> m a
    return      = pure

通过定义pure = return并忘记手动实现return,可能会创建一个无限循环的定义,它将通过编译并且只能在运行时检测到。

>>目前是另一回事。它仅在>>=上有一个默认的实现中继:

(>>) :: forall a b. m a -> m b -> m b
m >> k = m >>= \_ -> k
除非您在*> = >>的定义中使用*>,否则您将无法通过>>=创建无限循环,但base关于可能的下一个>>中的重大更改(可能会将>> = *>的默认实施更改为*> = >>),因此不鼓励使用$redis-cli -h 127.0.0.1 -p 6379 -a mysupersecretpassword 进行向前兼容。

相关问题