3

私は次のタイプを持っています:

data S req rsp = Done rsp | Next req (rsp -> S req rsp)

アイデアは、ネットワーク通信の純粋な表現として使用することです。つまり、次のようになります。

... Next GetUser $ \uid -> Next (Login uid) $ \success -> Done success

これは、不純な function によって評価されますeval

さて、これは何ですか (あるとすれば?) 私が見る限り、これはモナドでも矢印でもありません。ストリーム/パイプ/オートマトン/fsm と継続モナドの間の何かのようです。これは、このタイプのものをより適切に表現することができるかもしれないと私に思わせますが、何ですか?

4

2 に答える 2

6

Free Monadです。evalアイデアは、関数のように複数のインタープリターを持つことができる命令の説明があるということです。Free Monad は、このタスクが持つパターンを抽象化します。詳細については、この素晴らしい投稿をお勧めします。

タイプを適応させるためにFree、次のことができます。

{-# LANGUAGE DeriveFunctor #-}

import Control.Monad.Free

data Instruction req rsp next =
  Respond rsp |
  Interact req (rsp -> next)
  deriving (Functor)

type S req rsp =
  Free (Instruction req rsp)

respond :: rsp -> S req rsp ()
respond rsp =
  liftF (Respond rsp)

interact :: req -> S req rsp rsp
interact req =
  liftF (Interact req id)

おかげでFree、はモナドになりました。これは、 APIを使用して関数と関数をS req rsp作成できるようになったことを意味します。respondinteractMonad

それだけではありません。respondおよび関数はinteract、テンプレート Haskell を使用して次の追加コードで生成できます。

{-# LANGUAGE TemplateHaskell #-}

import Control.Monad.Free.TH

makeFree ''Instruction
于 2016-10-23T13:40:47.527 に答える
5

あなたの型は、モナドとしても知られるアプフェルムスの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任意の.>>=fmapFunctor

于 2016-10-23T14:04:18.853 に答える