あなたの型は、モナドとしても知られるアプフェルムスのoperational
モナドに少し似ています。Freer
data Program inst a where
Return :: a -> Program inst a
Bind :: inst a -> (a -> Program inst b) -> Program inst b
instance Monad (Program inst) where
return = Return
Return x >>= f = f x
Bind i next >>= f = Bind i (fmap (>>= f) next)
-- plus the usual Functor and Applicative boilerplate
Program :: (* -> *) -> * -> *
命令 のシーケンスを表し、inst
型パラメーターを使用して、インタープリターでその命令を実行する「戻り値の型」を示します。コンストラクターは、命令のBind
結果がインタープリターから受信された後に実行できる命令と継続を受け取ります。がどのように存在量化されているかに注意してくださいa
。これは、計算のすべての中間ステップの型が全体の型に関連していないという事実を反映しています。
と your typeの重要な違いProgram
は、応答の型が計算全体にわたって固定されるのではなく、命令によって決定されることです。これにより、各リクエストが引き起こすことを期待するレスポンスについて、よりきめ細かい保証を行うことができます。
たとえば、次の状態モナドは次のように記述されますProgram
。
data StateI s r where
Get :: StateI s s
Put :: s -> StateI s ()
type State s = Program (StateI s)
get :: State s s
get = Bind Get Return
put :: s -> State s ()
put s = Bind (Put s) Return
modify :: (s -> s) -> State s ()
modify f = do
x <- get
put (f x)
runState :: State s a -> s -> (s, a)
runState (Return x) s = (s, x)
runState (Bind Get next) s = runState (next s) s
runState (Bind (Put s) next) _ = runState (next ()) s
余米田補題は、Program
が に同型であることを示していFree
ます。->
直観的に、これはのFunctor
インスタンスに基づく自由なモナドです。左連想バインドのような特定の操作でProgram
は、Free
任意の.>>=
fmap
Functor