跟踪 ST monad 中函数之间的多个引用的好方法吗?
我正在编写一些代码(Metropolis-Hastings MCMC 采样器),它将使用随机数生成器,并基于此修改数组和可能的其他结构。
我最初的想法是使用 ST monad,这样我就可以使用 ST 数组和 mersenne-random-pure64 包,将 PureMT 生成器保留为状态的一部分。
然而,我希望能够将一些工作分成单独的辅助函数(例如,在给定范围内采样随机整数,更新数组结构,以及可能更复杂的事情)。为此,我认为我需要将对 PureMT gen 的引用和数组传递给所有函数,如果我需要存储更多状态,这很快就会变得非常难看。
我的本能是将所有状态分组为一个可以在任何地方访问的数据类型,就像我通过定义新数据类型来使用 State monad 一样,但我不知道 ST monad 或正确的做法。
做这类事情有什么好的模式吗?我想让事情尽可能通用,因为我可能需要添加额外的状态并围绕现有部分构建更多的单子代码。
我尝试寻找 ST monad 代码的示例,但 Real World Haskell 中似乎没有涵盖它,并且 haskell wiki 示例非常简短。
谢谢!
I'm writing some code (a Metropolis-Hastings MCMC sampler) that will use a random number generator, and modify an array and potentially other structures based on this.
My initial idea was to use the ST monad, so that I could use ST arrays and the mersenne-random-pure64 package, keeping the PureMT generator as part of the state.
However I want to be able to split off some of the work into separate helper functions (e.g to sample a random integer in a given range, to update the array structure, and potentially more complicated things). To do this, I think I would need to pass the references to the PureMT gen and the array to all the functions, which could quickly become very ugly if I need to store more state.
My instinct is to group all of the state into a single data type that I can access anywhere, as I would using the State monad by defining a new datatype, but I don't know if that is possible with the ST monad, or the right way to go about it.
Are there any nice patterns for doing this sort of thing? I want to keep things as general as possible because I will probably need to add extra state and build more monadic code around the existing parts.
I have tried looking for examples of ST monad code but it does not seem to be covered in Real World Haskell, and the haskell wiki examples are very short and simple.
thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里要认识到的关键点是,您使用的是
ST
完全不相关。ST
引用本身只是常规值,您需要在多个位置访问它们,但您实际上并不想更改它们!可变性发生在ST
中,但STRef
值等基本上是只读的。它们的名称指向可变数据。当然,Reader monad 的用途就是对周围环境进行只读访问。对所有函数的引用的丑陋传递正是它为您所做的事情,但因为您已经在
ST
中,所以您可以将其作为 monad 转换器使用。举一个简单的例子,您可以这样做:为了更通用,您可以对引用类型的详细信息进行抽象 ,并将其变成一个通用的“具有可变引用的环境”monad。
The key point to realize here is that it's completely irrelevant that you're using
ST
. TheST
references themselves are just regular values, which you need access to in a variety of places, but you don't actually want to change them! The mutability occurs inST
, but theSTRef
values and whatnot are basically read-only. They're names pointing to the mutable data.Of course, read-only access to an ambient environment is what the
Reader
monad is for. The ugly passing of references to all the functions is exactly what it's doing for you, but because you're already inST
, you can just bolt it on as a monad transformer. As a simple example, you can do something like this:For more generality, you could abstract over the details of the reference types, and make it into a general "environment with mutable references" monad.
您可以像使用 IO monad 一样使用 ST monad,但请记住,您只能获得数组和引用,而没有其他 IO 好处。就像 IO 一样,如果您想通过计算透明地线程化某些状态,您可以在其上分层 StateT。
You can use the ST monad just like the IO monad, bearing in mind that you only get arrays and refs and no other IO goodies. Just like IO, you can layer a StateT over it if you want to thread some state transparently through your computation.