haskell - 带 Haskell 管道的有状态生成器

标签 haskell haskell-pipes

  1. 假设我想使用 Haskell 管道对一个 Python Generator[int, None, None] 保持一些内部状态。应该 我正在使用 Producer int (State s) ()StateT s (Producer int m) (),其中 m 是任何类型的效果我最终想要从 消费者?

  2. 我应该如何考虑管道中换能器的概念?所以在 奥列格的 simple generators , 有

    type Transducer m1 m2 e1 e2  = Producer m1 e1 -> Producer m2 e2
    

    但我不知道管道中的模拟是什么,因为任何 Proxy 交互的对象似乎依赖于相同的底层 monad m, 不从 m1 切换到 m2。查看Prelude函数,对于 实例。

我想我只是误解了有关管道工作方式的一些基本知识。感谢您的帮助。

最佳答案

pipes 中,您通常不会在整体 Effect 的基本 monad m 中使用 effects 来模拟内部 Producer 的状态。如果你真的想为此目的使用 State ,它将是相关 Producer 的内部实现细节(由 runStatePevalStatePProducer 中,如下所述),并且 State 不会出现在 Producer 的类型中.

同样重要的是要强调 Producer,即使它在 Identity 基础 monad 中运行而没有任何“效果”可供其支配,也不是某种类型的没有 monadic 帮助的情况下,可以不断产生相同值的纯函数。 Producer 基本上是一个流,它可以使用通常的功能机制(例如递归)来维护状态。因此,您绝对不需要 State 来使 Producer 成为有状态的。

结果是 Pipes 中的 Python Generator[int, None, None] 的通常模型只是一个 Monad m => Producer Int m () 在未指定的基 monad m 中多态。只有当 Producer 需要一些外部效果(例如,IO 来访问文件系统)时,您才需要更多的 m(例如,一个 >MonadIO m 约束或其他东西)。

举个具体的例子,生成伪随机数的Producer显然有“状态”,但典型的实现是“纯”Producer:

randoms :: (Monad m) => Word32 -> Producer Int m ()
randoms seed = do
  let seed' = 1664525 * seed + 1013904223
  yield $ fromIntegral seed'
  randoms seed'

通过递归维护状态。

如果您真的决定通过 State monad 维护此状态,Producer 的类型将不会改变。您只需在内部使用 StatePipes.Lift 模块提供了一些帮助程序(如此处使用的 evalStateP)来在本地添加一个 monad 层以促进此操作:

randoms' :: (Monad m) => Word32 -> Producer Int m ()
randoms' seed = evalStateP seed $ forever $ do
  x <- get
  let x' = 1664525 * x + 1013904223
  yield $ fromIntegral x'
  put x'

Oleg 的简单生成器完全不同。他的生产者和消费者通过单子(monad)效应生产和消费值(value),而“改变单子(monad)”是实现的核心。特别是,我相信他的消费者和转换器可以通过单子(monad)效应来维持状态,例如 State 单子(monad),尽管我必须更仔细地观察才能做到当然。

相比之下,pipes 代理可以产生和消费值并维持独立于底层基础 monad 的内部状态。

最终,pipes 中 Oleg 转换器的模拟只是 Pipe。两者都消耗生产者的值(value)并向消费者产生值(value)。 Oleg 的转换器中的 monad 变化只是一个实现细节。

关于haskell - 带 Haskell 管道的有状态生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71686259/

相关文章:

sql - 如何避免在使用 haskell 解析 sql 时将 WHERE 视为属性

haskell - Haskell 如何推断类型类的定义?

haskell - 管道的上游类型参数的真正好处是什么?

haskell - 管道 3.0 : non linear topologies

haskell - 为什么不打印强制整个惰性 IO 值?

haskell - 流媒体库中惯用的预取

haskell-pipes - 使用 haskell 管道字节串逐行迭代文件

haskell - 为 'lambda' , 'define' 生成 LLVM 代码

haskell - 处理 Either 和 ST monad

Haskell FFI - mallocForeignPtr 用法