gpt4 book ai didi

haskell - 为什么我的 MaybeT (State ) () 忽略状态更改?

转载 作者:行者123 更新时间:2023-12-02 21:33:36 25 4
gpt4 key购买 nike

简短版本:当我使用 runMaybeT 时然后runStateMaybeT (State <type>) () 类型的单子(monad)上,即使 Maybe 看起来也没有发生状态变化。结果等于Just () 。为什么?

完整版:我正在编写一个程序来解决汉诺塔的问题。我将解决方案表示为 State 列表单子(monad)在测序时会操纵初始 Towers状态:

data Towers = Towers [Int] [Int] [Int]
deriving (Show)
type Move = State Towers ()

towerMoves :: Int -> Rod -> Rod -> [Move]
towerMoves 1 r1 r2 = [pop r1 >>= push r2]
towerMoves n r1 r2 = topToTemp ++ (towerMoves 1 r1 r2) ++ topToFinal
where
r3 = other r1 r2
topToTemp = towerMoves (n - 1) r1 r3
topToFinal = towerMoves (n - 1) r3 r2

moves = towerMoves 5 First Third
initTowers = Towers [1,2,3,4,5] [] []

main = print $ snd $ runState (sequence_ moves) initTowers

到目前为止,该程序产生了正确的输出:

Towers [] [] [1,2,3,4,5]

然后,我想验证程序是否遵守拼图规则,即较大的圆盘(此处用数字表示)不会出现在较小的圆盘之前。我想在每个 Move 之后插入某种验证,所以我尝试使用 MaybeT monad 转换器将失败发送到移动列表:

verifiedMoves :: [MaybeT (State Towers) ()]
verifiedMoves = map ((>> verify) . return) moves
where
check :: [Int] -> Bool
check [] = True
check [_] = True
check (x:y:ys) = (x < y) && check (y:ys)
verify :: MaybeT (State Towers) ()
verify = do
(Towers xs ys zs) <- lift get
guard (check xs && check ys && check zs)

因此我更改了 main单子(monad):

main = maybe (putStrLn "violation") (const $ print finalTowers) v
where
(v, finalTowers) = runState (runMaybeT $ sequence_ verifiedMoves) initTowers

现在输出看起来错误,就像没有发生状态更改:

Towers [1,2,3,4,5] [] []

如果我把初始状态设为无效,确实验证失败了。因此,如果没有状态变化,因为 Move 的影响如果被打断,我希望输出是“违规”一词。

为什么,申请后runMaybeT ,是应用 runState 的结果等于 (Just (), Towers [1,2,3,4,5] [] [])

<小时/>

这是其余的代码,供引用。我试过lifting the get and put monads in my pop and push functions ,但是产生了相同的输出。

import Control.Monad
import Data.Functor.Identity
import Control.Monad.State
import Control.Monad.Trans.Maybe
import qualified Data.Map as M

data Rod = First | Second | Third
deriving (Show)

other :: Rod -> Rod -> Rod
other First Second = Third
other Second First = Third
other First Third = Second
other Third First = Second
other Second Third = First
other Third Second = First

getRod :: Towers -> Rod -> [Int]
getRod (Towers x y z) First = x
getRod (Towers x y z) Second = y
getRod (Towers x y z) Third = z

setRod :: Rod -> Towers -> [Int] -> Towers
setRod First t ds = Towers ds r2 r3
where
r2 = t `getRod` Second
r3 = t `getRod` Third
setRod Second t ds = Towers r1 ds r3
where
r1 = t `getRod` First
r3 = t `getRod` Third
setRod Third t ds = Towers r1 r2 ds
where
r1 = t `getRod` First
r2 = t `getRod` Second

pop :: Rod -> State Towers Int
pop r = do
t <- get
let ds = t `getRod` r
d = head ds
load = setRod r
put $ t `load` (tail ds)
return d

push :: Rod -> Int -> State Towers ()
push r d = do
t <- get
let ds = t `getRod` r
load = setRod r
put $ t `load` (d:ds)

最佳答案

看这一行

verifiedMoves = map ((>> verify) . return) moves

相当于

= map (\m -> return m >> verify) moves

但是对于所有x,我们都返回x >> a = a,因此

= map (\_ -> verify) moves

所以你放弃了这些 Action 。您可能想在那里使用 lift 而不是 return

关于haskell - 为什么我的 MaybeT (State <type>) () 忽略状态更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44956497/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com