9

ほとんどのモナド関数は純粋な引数を取り、モナド値を返します。ただし、モナド引数も必要なものがいくつかあります。たとえば、次のようになります。

mplus :: (MonadPlus m) => m a -> m a -> m a

finally :: IO a -> IO b -> IO a

forkIO :: m () -> m ThreadId

-- | From Control.Monad.Parallel
forkExec :: m a -> m (m a)

それらのそれぞれが異なる問題を引き起こしているようで、フリーモナドを使用してそのようなアクションをエンコードする一般的な方法を把握できません。

  • 両方finallyforkIO問題は、モナド引数が結果とは異なる型であることです。しかし、無料の場合は、のみをエンコードするIO aのようなエンコーディング タイプの型変数に置き換えられるため、それらが同じタイプである必要があります。data MyFunctor x = Finally x x xIO a -> IO a -> IO a

    著者が最初に実装するために使用するHaskellコードの 33 行のゼロから協調スレッドへFork next next

    cFork :: (Monad m) => Thread m Bool
    cFork = liftF (Fork False True)
    

    そして、それを使用して実装します

    fork :: (Monad m) => Thread m a -> Thread m ()
    

    入力と出力の型が異なります。しかし、これが何らかのプロセスを使用して導き出されたものなのか、それともこの特定の目的のために機能するアドホックなアイデアなのかはわかりません。

  • mplus特に紛らわしい: 単純なエンコーディング

    data F b = MZero | MPlus b b
    

    配布され>>=提案されたより良い実装はより複雑です。また、 free のネイティブ実装が freeからMonadPlus 削除されました

    freerでは、追加することで実装されます

    data NonDetEff a where
      MZero :: NonDetEff a
      MPlus :: NonDetEff Bool
    

    MPlus NonDetEff Boolの代わりにあるのはなぜNonDetEff a aですか?CoYoneda functorFreeを使用する以外に、データ型を functor にする必要がある で動作させる方法はありますか?

  • forkExecどうやって進めばいいのかわからないからです。
4

1 に答える 1

3

Freerモナドの部分だけお答えします。定義を思い出してください。

data Freer f b where
    Pure :: b -> Freer f b
    Roll :: f a -> (a -> Freer f b) -> Freer f b

今と

data NonDetEff a where
  MZero :: NonDetEff a
  MPlus :: NonDetEff Bool

定義できます

type NonDetComp = Freer NonDetEff

Rollに適用されるとMPlusaは と統合されBool、2 番目の引数の型Bool -> NonDetEff bは 基本的にタプルです:

tuplify :: (Bool -> a) -> (a, a)
tuplify f = (f True, f False)

untuplify :: (a, a) -> (Bool -> a)
untuplify (x, y) True  = x
untuplify (x, y) False = y

例として:

ex :: NonDetComp Int
ex = Roll MPlus $ Pure . untuplify (1, 2)

MonadPlusしたがって、非決定論的計算のインスタンスを定義できます

instance MonadPlus NonDetComp where
    mzero       = Roll MZero Pure
    a `mplus` b = Roll MPlus $ untuplify (a, b)

そしてそれらを実行します

run :: NonDetComp a -> [a]
run (Pure x)       = [x]
run (Roll MZero f) = []
run (Roll MPlus f) = let (a, b) = tuplify f in run a ++ run b
于 2015-12-21T10:34:03.690 に答える