2009-06-07
Control.MonadをApplicativeで
d:id:Otter_O:20080301:1204363038を見て、Control.Monadにあるユーティリティ関数をApplicativeで書き換えてみた。
21個中15個を書き換えることが出来た。
(=<<) :: Monad m => (a -> m b) -> m a -> m b (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c join :: Monad m => m (m a) -> m a foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a foldM_ :: Monad m => (a -> b -> m a) -> a -> [b] -> m ()
これらは実行の結果を受け渡す機能が必要なので実装できなかった。
トラックバック - http://haskell.g.hatena.ne.jp/illillli/20090607
こうやって見るとMonadとApplicativeの違いが浮き彫りになるようにも見えますね…
クラスメソッドレベルではこうした違いが見えているのに、モナドのインスタンス型であるIO, Maybe, Listなどそれぞれ実はApplicativeのインスタンスであるところもなんだか不思議です。
Control.Monad.apがMonadな型のApplicative.<*>のインプリメンテーションに使われているので、Applicativeが要求しているのはモナドに格納されている中身の型のほうで、MonadとApplicaiveとの間では根本的な不適合は無いようにも見えますね…
これからもよろしくどうぞ。
結局 join :: m (m a) -> m a があればApplicativeとモナドは同じ機能を持つことになりそうです。
公式のメーリングリストのほうで「最適化したいので *> :: f a -> f b -> f b をApplicativeのクラスメソッドに含めて欲しい」という話が出ていました。
モナドのほうでも最適化のために >> がクラスメソッドに含められているので、この点でも似ている/同じ使われ方をされているのだろうと思います。