私はこのようなことをしようとしています:
processListIO :: [A] -> IO [B]
processListIO xs = bracket ini fin $ \s -> mapM (upd s) xs
where
ini :: IO (Ptr S)
upd :: Ptr S -> A -> IO B
fin :: Ptr S -> IO ()
基本的に、これはリストを反復処理し、各要素を別のものにマップし、プロセスで内部のプライベート状態を使用する計算です。特定ini
の 、upd
、およびfin
私は C ライブラリから来ていることを念頭に置いていますが、それらは単に新しい状態を割り当て、唯一の副作用が状態を変更する計算を実行し、状態の割り当てを解除するという点で「うまく動作する」ことが保証されています. これは、安全に前に置いunsafePerformIO
て純粋な関数を取得できることを意味すると思います。
processList :: [A] -> [B]
processList = unsafePerformIO . processListIO
今、私は同じことをしたいと思いますが、conduit
(または、実際には他のストリーミング ライブラリ) を使用します。ただし、計算は本質的に効果がないため、コンジットを純粋にしたいと思います。
processStream :: ConduitT A B Identity ()
またはさらに良い:
processStream :: forall m. Monad m => ConduitT A B m ()
(要素が純粋であるという理由だけで、このトリックは単純なリストで非常にうまく機能するように見えるため、後者は意味をなさないのではないかと思います。)
理想的には、計算には状態が必要であり、外部呼び出しを行うという事実をユーザーから完全に隠し、それが単なる a scanl
(またはmapAccum
とconduit
呼ばれる) のようなものであると偽る必要があります。
これは可能ですか?conduit
(または他のストリーミング ライブラリ)でこれを行うにはどうすればよいですか?