web-dev-qa-db-ja.com

haskellで新しいモナドを定義すると、Applicativeのインスタンスが発生しません

新しいモナドを定義しようとしていますが、奇妙なエラーが発生しています

newmonad.hs

 newtype Wrapped a = Wrap {unwrap :: a} 
 instance Monad Wrapped where 
(>> =)(Wrap x)f = fx 
 return x =ラップx 
 
 main = do 
 putStrLn "yay" 
 $ ghc --version 
 Glorious Glasgow Haskell Compilation System、バージョン7.10.1 
 
 $ ghc newmonad.hs 
 [1 of 1 ]コンパイルMain(newmonad.hs、newmonad.o)
 
 newmonad.hs:2:10:
(Applicative Wrapped)
のインスタンスはインスタンス宣言のスーパークラス
「Monad Wrapped」のインスタンス宣言内

Applicativeのインスタンスを定義する必要があるのはなぜですか?

53
fakedrake

これはApplicative Monad Proposal(AMP)です。何かをMonadとして宣言するときはいつでも、それをApplicativeとして宣言する必要があります(したがって、Functor)。数学的に言えば、すべてのモナド適用ファンクターなので、これは理にかなっています。

以下を実行して、エラーを除去できます。

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

Edit:たぶん、これがrecentであることをより明確に指摘すべきでしょうか?投稿したコードは以前は機能していましたが、GHCのrecentバージョンではエラーが発生します。それは壊滅的な変化です。

Edit:次の宣言は、anyモナドに対して機能するはずです:

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

問題のモナドによっては、より効率的な実装が可能かもしれませんが、これは簡単な出発点です。

81

最も標準化された控えめな答えは次のとおりです。

monadはApplicativeに依存しているため

class Applicative m => Monad m where ...

applicativeはFunctorに依存しています

class Functor f => Applicative f where ...

インスタンス定義が必要です

> instance Functor Wrapped where
>     fmap = liftM

そして

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