如何在 Haskell 中构建一个不确定的状态单子?

Posted

技术标签:

【中文标题】如何在 Haskell 中构建一个不确定的状态单子?【英文标题】:How can I build a nondeterministic state monad in Haskell? 【发布时间】:2012-12-12 16:00:35 【问题描述】:

我想在 Haskell 中构建一个不确定的状态单子。这将允许我使用构建状态生成搜索空间中的所有元素以修剪不良位置。假设我有以下(伪)代码:

primitives :: [State Int Element] 
primitives = [... list of primitive stateful elements ...]                                                                                                                      
combine :: Element -> Element -> State Int Element                                                                                                            
expand :: Depth -> [State Int Element]                                                                                                                        
expand 0 = primitives                                                                                                                                         
expand d = do                                                                                                                                                 
  ... do something to the state ...                                                                                                                           
  left <- expand (d-1)                                                                                                                                        
  right <- expand (d-1)                                                                                                                                       
  let out = combine left right                                                                                                                                
  guard ( ... some check on out ... )                                                                                                                         
  return out        

这里有几件事是行不通的:我需要了解的最基本的事情是如何做一些事情来陈述,然后将其传递到每个expand 分支。我用State Int [ State Int Element] 类型的函数尝试了很多方法,但最终,一旦我将列表单子的分支包装在状态包装器中,我就无法删除它,对吧?那么有没有办法做到这一点?

谢谢。

【问题讨论】:

StateT monad 允许您跟踪状态,同时还可以使用另一个 monad,例如 IO 或 Rand(用于随机值)。如果我正确理解了您的问题,我认为 StateT 将解决您的问题。您能否举例说明您希望在 primitives 数组中包含哪些内容? 听起来像 LogicT monad 转换器:hackage.haskell.org/package/logict,你的非确定性状态 monad 是 LogicT (State Int) Element。公平的连词,条件和修剪作为奖励。比简单的列表更有效的实现。 一般说明:不要构建自己的组合 monad,使用 monad 转换器。 【参考方案1】:

一个简单的State monad 定义为:

data State s a = State (s -> (a, s))

这代表了一个自包含和确定性的有状态计算。将[] 视为非确定性monad,您可以使用[State s a],它表示一组非确定性计算,或State s [a],它表示产生一组非确定性值的确定性计算。在这两种情况下,有状态计算本身的结构中都不存在任何不确定性。

要以您想要的方式实际结合状态和非确定性行为,您需要以仅使用State 无法实现的方式将两者结合起来;这就是monad转换器的目的。 StateT s [] a 类型等价于:

data NonDetState s a = NonDetState (s -> [(a, s)])

这给您带来的是状态值的不确定性,在计算中的任何一点都只能观察到个人选择。

不允许允许的是分支之间的任何交互;在一个分支中进行的状态更改将永远不会从其他分支中看到,这在非确定性计算中通常是需要的。

【讨论】:

以上是关于如何在 Haskell 中构建一个不确定的状态单子?的主要内容,如果未能解决你的问题,请参考以下文章

Haskell 中的单子——洪峰老师讲创客道(三十五)

在haskell中构建一个非确定性的monad转换器

Haskell 中的非确定性是啥?

VBO/FBO/DisplayLists 如何在 Haskell 的 OpenGL 绑定中工作?

我想我找到了一个“不存在的单子”

Haskell概率单子的类型类问题