質問

Pipeは、 Generator パート(yield)と Consumer Part(await)との2つの部分に分割できます。

Generator Hareのみを使用しているPipeを使用している場合は、()(または未返信)のみを返す場合は、「ListT Donegred」として表すことができます。 MonadPlusを使用してListt-Done-Rightのようなものを表すことができます。

http://www.reddit.com/r/haskell/comments. / 2bpsh7 / a_simple_monadic_stream_library / cj7sqtw?context= 3

だから私の質問はこれです:パイプの消費者部分のためのListtとMonadplusには、Listtへの二重がありますか?

要件:

  • yieldを使用しないパイプで、()(または未返信)のみを返しますが、この「デュアルからListt」として表示できます。
  • 「派閥からListt」は、「Monadplusのデュアル」に一般化することができます
役に立ちましたか?

解決

答えは「発電機のような」タイプクラスを締め付けることではなく、Categoryawait / (>~)カテゴリと同等の単純なpipesインスタンスで拡張することです。

残念ながら、これを3つの型クラス(MonadPlus、GeneraCodeTagCode、およびMonadTrans)を満たすようにするようにタイプ変数を配置する方法はありませんので、新しい型クラスを定義します。

{-# LANGUAGE KindSignatures #-}

import Control.Monad
import Control.Monad.Trans.Class

class Consumer (t :: * -> (* -> *) -> * -> *) where
    await :: t a m a
    (>~)  :: t a m b -> t b m c -> t a m c
.

このタイプのクラスの法律はカテゴリー法則です:

await >~ f = f

f >~ await = f

(f >~ g) >~ h = f >~ (g >~ h)
.

この追加タイプクラスを使用したら、CategorysとConsumersの両方を実装できます。

printer :: (Show a, Monad (t a IO), MonadTrans (t a), Consumer t) => t a IO r
printer = do
    a <- await
    lift (print a)
    printer
{-
printer :: Show a => Consumer a IO r
printer = do
    a <- await
    lift (print a)
    printer
-}

cat :: (MonadPlus (t a m), Consumer t) => t a m a
cat = await `mplus` cat
{-
cat :: Monad m => Pipe a a m r
cat = do
    a <- await
    yield a
    cat
-}

debug :: (Show a, MonadPlus (t a IO), MonadTrans (t a), Consumer t) => t a IO a
debug = do
    a <- await
    lift (print a)
    return a `mplus` debug
{-
debug :: Show a => Pipe a a IO r
debug = do
    a <- await
    lift (print a)
    yield a
    debug
-}

taker :: (Consumer t, MonadPlus (t a m)) => Int -> t a m a
taker 0 = mzero
taker n = do
    a <- await
    return a `mplus` taker (n - 1)
{-
taker :: Monad m => Int -> Pipe a a m ()
taker 0 = return ()
taker n = do
    a <- await
    yield a
    taker (n - 1)
-}
.

ハード部分は、Pipeに新しい型クラスを追加することなくこれを行う方法を考え出すことです。可能であれば、NewTypeでタイプをラップする関数だけでbaseCategoryを使用しているだけで、awaitインスタンスを使用してから、それを解除しています。それをする方法。

編集:解決策を見つけました。次のnewtypeを定義するだけです。

{-# LANGUAGE KindSignatures, FlexibleContexts #-}

import Control.Category
import Prelude hiding ((.), id)

newtype Consumer t m a b = Consumer { unConsumer :: t a m b }

await :: Category (Consumer t m) => t a m a
await = unConsumer id

(>~) :: Category (Consumer t m) => t a m b -> t b m c -> t a m c
f >~ g = unConsumer (Consumer f >>> Consumer g)
.

その後、任意のライブラリは、(>~) NewTypeでラップされたそれらのタイプのCategoryインスタンスを実装するだけです。

そのような制約は、CategoryまたはConsumerを使用したときに、このような制約を受けるでしょう:

cat :: (MonadPlus (t a m), Category (Consumer t m)) => t a m a
cat = await `mplus` cat
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top