Haskell 状态一元函数中的运行状态不工作

Haskell 状态一元函数中的运行状态不工作,haskell,random,state-monad,Haskell,Random,State Monad,我试图解决《人工智能-现代方法》一书中的问题2.8,这本书涉及一个单元格网格,并选择随机移动来导航网格 2.7为一个n X m的矩形房间设置一个环境,其中 正方形有5%的几率含有污垢,n和m在 随机范围为8到15,包括8到15 2.8设计并实施适用于以下环境的纯反射剂: 练习2.7,忽略回家的要求,并采取措施 它的性能 因此,我使用了两个状态单体-一个使用Grid作为状态,另一个使用StdGen作为状态。代码编译时没有任何错误,但当我从GHCi运行它时,它会被卡住并且不会返回 守则的有关部分:

我试图解决《人工智能-现代方法》一书中的问题2.8,这本书涉及一个单元格网格,并选择随机移动来导航网格

2.7为一个n X m的矩形房间设置一个环境,其中 正方形有5%的几率含有污垢,n和m在 随机范围为8到15,包括8到15

2.8设计并实施适用于以下环境的纯反射剂: 练习2.7,忽略回家的要求,并采取措施 它的性能

因此,我使用了两个状态单体-一个使用
Grid
作为状态,另一个使用
StdGen
作为状态。代码编译时没有任何错误,但当我从GHCi运行它时,它会被卡住并且不会返回

守则的有关部分:

支持代码

代码被卡在行中:

let (cleaner, grid) = runState (doAction GoForward cleaner) grid
我通过在代码中添加跟踪来确认这一点。对
doAction
函数的调用从未发生过

问题似乎是在
runCleaner
函数中使用了
runState
,但我找不到任何原因

请解释原因以及是否有办法解决此问题


另外,在一元函数中使用
runState
对我来说是错误的。请建议是否有更好的方法。

的右侧,让
绑定,绑定的名称在范围内,因此当您编写

let (cleaner, grid) = runState (doAction GoForward cleaner) grid
=
右侧的
清洁器
网格
与左侧的相同。当您将操作的输出作为输入反馈时,这可能会导致无限循环!为了避免这种情况,请为输出使用不同的名称

let (cleaner', grid') = runState (doAction GoForward cleaner) grid

除此之外,您完全正确地认为这样使用
runState
很奇怪。我认为如果将
doAction
的类型更改为

doAction :: Monad m => Action -> Cleaner -> StateT Grid m Cleaner
您没有提供此函数的主体,但我猜它仍然可以使用约束较少的类型签名

现在,您不必再费心手动获取和放置状态,因为
doAction
可以直接在monad中运行,而
chooseAction
可以通过先提升它来运行。使用此选项,可以更简洁地编写
案例
表达式:

cleaner <- case ph of
    [] -> doAction GoForward cleaner
    _  -> do action <- lift $ chooseAction (head ph)
             doAction action cleaner
清理器前进清理器
_->采取行动
let (cleaner', grid') = runState (doAction GoForward cleaner) grid
doAction :: Monad m => Action -> Cleaner -> StateT Grid m Cleaner
cleaner <- case ph of
    [] -> doAction GoForward cleaner
    _  -> do action <- lift $ chooseAction (head ph)
             doAction action cleaner