標準Monad
クラスには欠陥があり、実際に拡張する必要がある、Functor
またはPointed
浮かんでいるという考え。
私は必ずしもそれが正しいことだと主張しているわけではありませんが、誰かがそれをやろうとしていたとします:
import Prelude hiding (Monad(..))
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
join = (>>= id)
(>>=) :: m a -> (a -> m b) -> m b
a >>= t = join (fmap t a)
(>>) :: m a -> m b -> m b
a >> b = a >>= const b
これまでのところは問題ありませんが、do 表記法を使用しようとすると、次のようになります。
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
コンパイラは不平を言います:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
質問:
do 表記は に対してのみ機能しbase:GHC.Base.Monad
ますか? Monad
代替クラスで動作させる方法はありますか?
追加のコンテキスト:
私が本当にやりたいことはbase:Control.Arrow.Arrow
、「一般化された」Arrow
クラスに置き換えることです。
{-# LANGUAGE TypeFamilies #-}
class Category a => Arrow a where
type Pair a :: * -> * -> *
arr :: (b -> c) -> a b c
first :: a b c -> a (Pair a b d) (Pair a c d)
second :: a b c -> a (Pair a d b) (Pair a d c)
(***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
(&&&) :: a b c -> a b c' -> a b (Pair a c c')
そしてArrow
、クラスで の proc 表記を使用Arrow
しますが、上記の do 表記と の例のように失敗しますMonad
。
現在のクラスのような型コンストラクターではなく、主Either
にペア型コンストラクターとして使用します。これにより、私のおもちゃの RTS ゲーム ( ) のコードをよりきれいにすることができるかもしれません。(,)
Arrow
cabal install DefendTheKind