在haskell中定义一个新的monad不会引发Applicative的实例

时间:2015-07-27 11:57:11

标签: haskell monads

我正在尝试定义一个新的monad,我收到一个奇怪的错误

newmonad.hs

newtype Wrapped a = Wrap {unwrap :: a}
instance Monad Wrapped where
  (>>=) (Wrap x) f =  f x
  return x = Wrap x

main = do
  putStrLn "yay"
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.1

$ ghc newmonad.hs 
[1 of 1] Compiling Main             ( newmonad.hs, newmonad.o )

newmonad.hs:2:10:
    No instance for (Applicative Wrapped)
      arising from the superclasses of an instance declaration
    In the instance declaration for ‘Monad Wrapped’

为什么我需要定义Applicative的实例?

2 个答案:

答案 0 :(得分:79)

这是适用的Monad提案(AMP)。现在,只要您将某些内容声明为Monad,您就必须将其声明为Applicative(因此Functor)。从数学角度讲,每个monad 都是一个应用函子,所以这是有道理的。

您可以执行以下操作来删除错误:

instance Functor Wrap where
  fmap f (Wrap x) = Wrap (f x)

instance Applicative Wrap where
  pure = Wrap
  Wrap f <*> Wrap x = Wrap (f x)

https://wiki.haskell.org/Functor-Applicative-Monad_Proposal

编辑:也许我应该更清楚地指出这是最近的事情?您发布的代码之前曾用过,但是使用最近版本的GHC,您将收到错误消息。这是一个突破性的变化。

修改:以下声明适用于任何 monad:

import Control.Applicative -- Otherwise you can't do the Applicative instance.
import Control.Monad (liftM, ap)

instance Functor ??? where
  fmap = liftM

instance Applicative ??? where
  pure  = return
  (<*>) = ap

根据所讨论的monad,可能会有更高效的实现,但这是一个简单的起点。

答案 1 :(得分:1)

最规范,最简单的答案是:-

因为Monad依赖于应用性

  

class Applicative m => Monad m其中...

而Applicative取决于Functor

  

类Functor f =>适用于f,其中...

我们需要实例定义

> instance Functor Wrapped where
>     fmap = liftM

> instance Applicative Wrapped where
>     pure = return
>     (<*>) = ap