简体   繁体   English

有 Haskell 个管道的状态生成器

[英]Stateful generators with Haskell pipes

  1. Suppose I want to model, using Haskell pipes, a Python Generator[int, None, None] which keeps some internal state. Should I be using Producer int (State s) () or StateT s (Producer int m) () , where m is whatever type of effect I eventually want from the consumer?假设我想要 model,使用 Haskell 管道,Python Generator[int, None, None]保留一些内部 state。我应该使用Producer int (State s) ()还是StateT s (Producer int m) () ,其中m是我最终希望从消费者那里得到的任何类型的效果?

  2. How should I think about the notion of transducers in pipes?我应该如何考虑管道中换能器的概念? So in Oleg's simple generators , there is所以在 Oleg 的简单生成器中,有

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

    but I don't know what the analog is in pipes, because any Proxy objects that interact seem to rely on the same underlying monad m , not switching from m1 to m2 .但我不知道管道中的模拟是什么,因为任何交互的Proxy对象似乎都依赖于相同的底层 monad m ,而不是从m1切换到m2 See the Prelude functions, for instance.例如,请参阅Prelude函数。

I think I'm just misunderstanding something fundamental about the way pipes works.我想我只是误解了管道工作方式的一些基本知识。 Thanks for your help.谢谢你的帮助。

In pipes , you typically wouldn't use effects in the base monad m of your overall Effect to model the internal state of a Producer .pipes中,您通常不会在整体Effect的基本 monad m中使用 effects 到 model Producer内部state。 If you really wanted to use State for this purpose, it would be an internal implementation detail of the Producer in question (discharged by a runStateP or evalStateP inside the Producer , as explained below), and the State would not appear in the Producer 's type.如果您真的想为此目的使用State ,它将是相关Producer的内部实现细节(由Producer内部的runStatePevalStateP ,如下所述),并且State不会出现在Producer的类型。

It's also important to emphasize that a Producer , even when it's operating in the Identity base monad without any "effects" at its disposal, isn't some sort of pure function that would keep producing the same value over and over without monadic help.同样重要的是要强调一个Producer ,即使它在Identity base monad 中运行而没有任何“影响”可供其支配,也不是某种纯粹的 function ,它会在没有 monadic 帮助的情况下一遍又一遍地产生相同的值。 A Producer is basically a stream, and it can maintain state using the usual functional mechanisms (eg, recursion, for one).一个Producer基本上是一个 stream,它可以使用通常的功能机制(例如,递归)来维护 state。 So, you definitely don't need a State for a Producer to be stateful.因此,您绝对不需要State来使Producer有状态。

The upshot is that the usual model of a Python Generator[int, None, None] in Pipes is just a Monad m => Producer Int m () polymorphic in an unspecified base monad m .结果是 Pipes 中 Python Generator[int, None, None]的通常Pipes只是一个Monad m => Producer Int m ()在未指定的基础 monad m中多态。 Only if the Producer needs some external effects (eg, IO to access the filesystem) would you require more of m (eg, a MonadIO m constraint or something).只有当Producer需要一些外部效果(例如, IO来访问文件系统)时,您才会需要更多的m (例如, MonadIO m约束或其他东西)。

To give you a concrete example, a Producer that generates pseudorandom numbers obviously has "state", but a typical implementation would be a "pure" Producer :给你一个具体的例子,一个生成伪随机数的Producer显然有“状态”,但典型的实现是一个“纯” Producer

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

with the state maintained via recursion.通过递归维护 state。

If you really decided to maintain this state via the State monad, the type of the Producer wouldn't change.如果您真的决定通过State monad 维护这个 state, Producer的类型就不会改变。 You'd just use a State internally.您只需在内部使用State The Pipes.Lift module provides some helpers (like evalStateP used here) to locally add a monad layer to facilitate this: Pipes.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's simple generators are entirely different. Oleg 的简单生成器完全不同。 His producers and consumers produce and consume values only through monadic effects, and "monad changing" is central to the implementation.他的生产者和消费者通过单子效应来生产和消费价值,而“改变单子”是实现的核心。 In particular, I believe his consumers and transducers can only maintain state via a monadic effect, like a State monad, though I'd have to look a little more carefully to be sure.特别是,我相信他的消费者和传感器只能通过单子效应来维持 state,就像State单子一样,尽管我必须更仔细地观察才能确定。

In contrast, pipes proxies can produce and consume values and maintain internal state independent of the underlying base monad.相比之下, pipes代理可以产生和消费值并维护内部 state 独立于底层基础 monad。

Ultimately, the analog of Oleg's transducers in pipes are simply the Pipe s.最终,奥列格在pipes中的传感器的模拟只是Pipe s。 Both consume values from a producer and yield values to a consumer.两者都消耗生产者的价值并向消费者产生价值。 The monad changing in Oleg's transducers is just an implementation detail. Oleg 的转换器中的 monad 变化只是一个实现细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM