我必须在Haskell中编写一个程序来解决一些不确定性问题。 我认为我理解列表Monad的75%所以它是无意识的选择,但是......
(我的问题是用船和水填充n x m板我得到了行和柱的总和,船的每个部分都有它的价值,现在它并不重要。)
我想尽早保护以使算法有效问题是船舶插入的可能性取决于我给出的东西/我在插入的流行动作让我们称之为板状态我不知道如何通过它因为我不能单独从板上生成新的状态)
我的算法是: 1.初始化第一板 2.生成第一行尝试应用每个可能的插入(我可以插入绵羊verticaly所以我需要记住在下排插入绵羊的其他部分) 3.解决较小板的问题(在生成每两行后,我检查一切正常)
但是我不知道我怎么能通过新的状态因为我已经读过关于State Monad它只从旧状态生成新状态这对我来说是不可能的,我想在做操作时产生新的状态价值观。)
我很抱歉我对Haskell的仇恨,但经过几年的命令式语言编程被强迫与那些Monads战斗,做其他语言我几乎可以写的东西让我发疯。 (好吧,Haskell中的其他东西对我来说很好,其中一些实际上非常好)。
答案 0 :(得分:9)
将StateT
与列表monad组合以获得所需的行为。
这是一个使用列表monad的非确定性的简单示例,同时仍保留先前选择的历史记录:
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.State
fill :: StateT [Int] [] [Int]
fill = do
history <- get
if (length history == 3)
then return history
else do
choice <- lift [0, 1, 2]
guard (choice `notElem` history)
put (choice:history)
fill
fill
为其尝试的每个路径维护单独的历史记录。如果它填满了它,它会成功返回,但如果当前选择与之前的选择重叠,它会放弃该解决方案并尝试不同的路径。
您使用evalStateT
运行它,提供初始空记录:
>>> evalStateT fill []
[[2,1,0],[1,2,0],[2,0,1],[0,2,1],[1,0,2],[0,1,2]]
它返回所有可能解决方案的列表。在这种情况下,恰好是我们可以填补董事会的所有排列的列表。