7

によって生成された標準のインタープリターモナドトランスフォーマーの簡略化されたバージョンがありますFreeT

data InteractiveF p r a = Interact p (r -> a)

type Interactive p r = FreeT (InteractiveF p r)

pは「プロンプト」でありr、「環境」です...次のようなものを使用してこれを実行します:

runInteractive :: Monad m => (p -> m r) -> Interactive p r m a -> m a
runInteractive prompt iact = do
  ran <- runFreeT iact
  case ran of
    Pure x -> return x
    Free (Interact p f) -> do
      response <- prompt p
      runInteractive prompt (f resp)

instance MonadFix m => MonadFix (FreeT (InteractiveF p r)) m a)
mfix = -- ???

このタイプは多かれ少なかれ...の制約されたバージョンにすぎないように感じStateTます...どちらかといえば...Interactive p r IOの制約されたバージョンだIOと思います...私は思う...しかし...まあ、いずれにせよ、私の直感はそれを言います良い例があるはずです。

書いてみましたが、よくわかりません。これまでの私の最も近い試みは次のとおりです。

mfix f = FreeT (mfix (runFreeT . f . breakdown))
  where
    breakdown :: FreeF (InteractiveF p r) a (FreeT (InteractiveF p r) m a) -> a
    breakdown (Pure x) = x
    breakdown (Free (Interact p r)) = -- ...?

MonadFixのインスタンスを利用したバージョンも試してみましたmが、うまくいきませんでした -

mfix f = FreeT $ do
  rec ran <- runFreeT (f z)
      z   <- case ran of
               Pure x -> return x
               Free iact -> -- ...
  return -- ...

これが本当に可能かどうか、または不可能な理由を知っている人はいますか? もしそうなら、私が探し続けるのに適した場所はどこですか?


あるいは、私の実際のアプリケーションでは、実際に使用する必要さえありませんFreeT...使用するだけFreeです。つまり、Interactiveただのモナド変換子ではなく、ただのモナドであり、

runInteractive :: Monad m => (p -> m r) -> Interactive p r a -> m a
runInteractive _ (Pure x) = return x
runInteractive prompt (Free (Interact p f) = do
    response <- prompt p
    runInteractive prompt (f response)

一般的な FreeT のケースではなく、このケースで何かが可能であれば、私も嬉しいです:)

4

2 に答える 2

2

MonadFix m => MonadFix (Interactive p r)インスタンスを書き込むことはできません。

YourInteractiveFは、よく研究されているMoore machineの基本関手です。Moore マシンは出力 (あなたの場合はプロンプト) を提供し、入力 (あなたの場合は環境) に基づいて次に行うべきことを決定します。Moore マシンは常に最初に出力します。

data MooreF a b next = MooreF b (a -> next)
    deriving (Functor)

のインスタンスの記述に関するCA McCann の議論に従いますが、 の特定のケースに限定すると、 のインスタンスが存在する場合、関数が存在する必要があると最終的に判断されます。MonadFixFreeFree (MooreF a b)MonadFixFree (MooreF a b)

mooreFfix :: (next -> MooreF a b next) -> MooreF a b next

この関数を記述するには、 を構築する必要がありMooreF b (f :: a -> next)ます。b出力する sはありません。b次の が既にある場合は を取得できると考えられますaが、Moore マシンは常に最初に出力します。

Let in Stateのように

mooreFfix1つだけ先を読んでいれば、近いものを書くことができますa

almostMooreFfix :: (next -> MooreF a b next) -> a -> MooreF a b next
almostMooreFfix f a = let (MooreF b g) = f (g a)
                      in (MooreF b g)

その場合、引数とは独立しfて決定できることが不可欠になります。使用可能なすべてのs は、およびが他の関数であるという形式です。gnextff next = MooreF (f' next) g'f'g'

almostMooreFFix :: (next -> b) -> (a -> next) -> a -> MooreF a b next
almostMooreFFix f' g' a = let (MooreF b g) = f (g a)
                          in (MooreF b g)
                          where
                              f next = MooreF (f' next) g'

いくつかの等式の推論により、右辺を置き換えることができfますlet

almostMooreFFix :: (next -> b) -> (a -> next) -> a -> MooreF a b next
almostMooreFFix f' g' a = let (MooreF b g) = MooreF (f' (g a)) g'
                          in (MooreF b g)

にバインドgg'ます。

almostMooreFFix :: (next -> b) -> (a -> next) -> a -> MooreF a b next
almostMooreFFix f' g' a = let (MooreF b _) = MooreF (f' (g' a)) g'
                          in (MooreF b g')

にバインドbすると不要f' (g' a)letなり、関数には再帰的な結び目がありません。

almostMooreFFix :: (next -> b) -> (a -> next) -> a -> MooreF a b next
almostMooreFFix f' g' a = MooreF (f' (g' a)) g'

ではないすべてのalmostMooreFFixes は.undefinedさえ必要としませんlet

于 2015-03-21T03:09:11.673 に答える