2

iterateeとenumeratorの概念に関するチュートリアルを読み、それらがどのように機能するかを学習する方法としてサンプルバージョンを実装しました。ただし、iterateeパッケージで使用されるタイプは、私が見つけたどのチュートリアルとも大きく異なります。たとえば、Iterateeは次のように定義されます。

Iteratee     
   runIter :: forall r. (a -> Stream s -> m r) 
           -> ((Stream s -> Iteratee s m a) 
           -> Maybe SomeException -> m r) 
           -> m r

私はそれで何をするつもりなのか本当に理解していません。このバージョンの使用に関するチュートリアルはありますか、また、なぜこのように書かれたのか(つまり、Olegが行った元の方法に比べてどのような利点があるのか​​)。

4

2 に答える 2

2

免責事項:私はiterateeの現在のメンテナーです。

iteratee Examplesディレクトリにあるファイルのいくつかは、ライブラリの使用方法を理解するのに役立つ場合があります。word.hsはおそらくフォローするのが最も簡単です。

runIter基本的に、カスタム列挙を作成しない限り、ユーザーは使用する必要はありません。反復は、提供されたプリミティブを組み合わせることによって作成できます。また、、、、liftIおよびidone関数と組み合わせてicont、列挙し、runまたはで実行することもできtryRunます。

Olegには、2つの「元の」バージョンと1つのCPSバージョン(および場合によっては他のバージョン)があります。元のバージョンは両方ともhttp://okmij.org/ftp/Haskell/Iteratee/IterateeM.hsにあります。1つ目は実際のコードで、2つ目はコメントにあります。1つ目は、通常のとの代わりに、いくつかの特別な関数とを必要>>==とします。2つ目は標準関数を使用できますが、残念ながら、このバージョンでの単調な順序付けについて推論することは非常に困難です。他にもいくつかの欠点があります。CPSバージョンは、これらの問題をすべて回避します。そのため、iterateeを切り替えました。また、このスタイルで定義された反復はより短く、より読みやすいことがわかりました。残念ながら、CPSバージョンに固有のチュートリアルは知りませんが、Olegのコメント$$>>=$役に立つかもしれません。

于 2011-04-23T19:02:15.767 に答える
1

免責事項: 私は iteratee についてあまり知らず、一度も使用したことがありません。ですから、私の答えを一粒の塩で受け取ってください。

この定義は、Oleg のもの (より正確には、CPS スタイルの合計) と同等ですが、ひねりがあります: iteratee にアクセスすると、常にモナド値が返されることが保証されます。

オレグの定義は次のとおりです。

 data Iteratee el m a =
   | IE_done a
   | IE_cont (Maybe ErrMsg)
             (Stream el -> m (Iteratee el m a, Stream el))

done aしたがって、これは 、結果として与えaられたもの、またはcont (Maybe ErrMsg) (Stream el -> ...): 入力の別のチャンクと、場合によってはエラーが発生した場合に反復を継続する方法 (この場合、継続を継続することは計算を再開することになります)の合計です。

Either a bと同等であることはよく知られています: あなたにいずれかforall r. (a -> r) -> (b -> r) -> rを与えること、またはあなたが思いつく可能性のある変換の結果に対して、私はそのようなものを生成できることを約束することと同等です(そうするには、私が持っている必要があります) aまたは a )。ある意味では、 (Either ab) はデータを導入し、このデータを削除 します。そのような関数が と名付けられた場合、はsomeのパターン マッチングと同等です。abrabrabr. (a -> r) -> (b -> r) -> r case_abcase_ab (\a -> foo_a) (\b -> foo_b)case ab of { Left a -> foo_a; Right b -> foo_b }ab :: Either a b

したがって、ここに継続があります(ここで継続について話すのは 、「(a -> r)それが であることがわかったら、その値がどうなるか」を表すためaです)、オレグの定義と同等です:

data Iteratee el m a =
  forall r.
    (a -> r) ->
    ((Maybe ErrMsg), (Stream el -> m (Iteratee el m a, Stream el)) -> r) ->
     r

しかし、 iteratee の定義にはひねりがあります (無害なカリー化を法とする): 結果はそうではありませんr:m rある意味では、 iteratee のパターンマッチングの結果を常に monad に強制します m

data Iteratee el m a =
  forall r.
    (a -> m r) ->
    (Maybe ErrMsg -> (Stream el -> m (Iteratee el m a, Stream el)) -> m r) ->
     m r

最後に、Oleg の定義の「反復の継続」データはStream .. -> m (Iterate .., Stream ..)であるのに対し、 iteratee パッケージでは のみであることに注意してくださいStream -> Iteratee。ここでモナドを削除したのは、外側のレベルでそれを強制しているためだと思います (反復を適用すると、モナドに住むことを余儀なくされるので、後続の計算もモナドに住むことを強制するのはなぜですか?)。出力がもうない理由はわかりません。Streamこれは、それらの Iteratee が利用可能なときにすべての入力を消費する必要があることを意味していると思います (または、戻り値の型で「まだ終了していない」ロジックをエンコードしますa)。おそらく、これは効率上の理由によるものです。

于 2011-04-23T10:25:50.567 に答える