GHC 7.10.x 迁移:为什么不能在实例 Applicative 中写入 "pure = return"?
GHC 7.10.x migration: why can't one write "pure = return" in the instance Applicative?
我正在阅读一篇关于 GHC 7.10.x Migration 的文章。有一些修复错误的建议。
GHC says No instance for (Applicative ...)
If GHC complains that
Foo.hs:7:10:
No instance for (Applicative Foo) arising from the superclasses of an instance declaration
In the instance declaration for ‘Monad Foo’ then an easy way to fix this error is by defining an Applicative (and possibly a Functor)
instance: instance Functor Foo where
fmap = liftM
-- or alternatively:
-- 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。我试了一下,已经编译好了。
正如@WillSewell 在评论中暗示的那样,从 base-4.8.0.0
现在 return
类型 class 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
并且到 *> = >>
你不会创建一个无限循环,除非你在 >>=
的定义中使用 *>
,但是有 some concern 关于可能的下一个base
的重大变化(可能会将 >>
的默认实现更改为 >> = *>
),因此不鼓励 *> = >>
实现向前兼容性。
我正在阅读一篇关于 GHC 7.10.x Migration 的文章。有一些修复错误的建议。
GHC says
No instance for (Applicative ...)
If GHC complains that
Foo.hs:7:10: No instance for (Applicative Foo) arising from the superclasses of an instance declaration In the instance declaration for ‘Monad Foo’ then an easy way to fix this error is by defining an Applicative (and possibly a Functor) instance: instance Functor Foo where fmap = liftM -- or alternatively: -- 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。我试了一下,已经编译好了。
正如@WillSewell 在评论中暗示的那样,从 base-4.8.0.0
现在 return
类型 class 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
并且到 *> = >>
你不会创建一个无限循环,除非你在 >>=
的定义中使用 *>
,但是有 some concern 关于可能的下一个base
的重大变化(可能会将 >>
的默认实现更改为 >> = *>
),因此不鼓励 *> = >>
实现向前兼容性。