我正在构建代码以获得理解,实际上是一个Solitaire解算器。 我有一个简单的暴力实现,使用State monad,实际上只是为了证明我可以使用它(它只保留每个移动的计数)。 但是现在我想使用Unboxed Mutable数组来记录被访问的板,从而在我到达已经通过另一条路径访问的板位置时快速评估路径。 似乎ST monad不允许我线程隐式状态,但是我必须使用ST(或IO)才能访问Mutable数组。因此,似乎我必须结合两个Monads - State来线程化状态(实际上包括一个Mutable数组),另一个(ST)来获得Mutable数组函数。
答案 0 :(得分:5)
我不是百分之百确定ST monad是改善像这样的搜索任务的性能的方法。但假设它是......您可以通过将要保留的状态放入STRef
来“线程化状态”。你可以这样做而不需要将多个monad混合在一起,这样可以使事情变得更加简单。
如果你想要可变状态,你肯定需要ST或IO monad。 (或STM monad,但这只用于线程同步,这里你不需要。)
monad堆叠的顺序可能很重要 - 但在这种情况下,它不会。如果你有List monad和Error monad之类的东西,那么根据堆叠顺序,错误要么在列表中只有一种可能性,要么在列表中所有可能性。对于您的情况,没有任何效果会根据堆栈顺序而改变。
...这是幸运的,因为没有用于将物品变成ST的变压器。所以ST 已经成为内部monad。
说了这么多,再说一遍,我认为你真的不需要monad堆栈。我认为一个简单的STRef
会做。
答案 1 :(得分:4)
使用ST
时,你所拥有的任何数组或引用都不是State
monad意义上的 state :它们永远不会被修改!你可以把它们想象成一个指针;指针是不变的,虽然它指向的东西可能会改变。因此,您可以将数组或引用或其他任何内容作为函数参数传递给ST
操作。如果您希望StateT
操作需要返回不同的数组而不是传递的数组,那么ST
机制将是合适的 - 即不仅修改现有数组而且创造一个新鲜的。由于通常不是这种情况,StateT
不合适。
如果你真的想要一个monad变换器堆栈,你可以把你的数组和引用放到ReaderT
monad的环境中。但这可能不是必要的。