jak*_*iel 5 monads haskell state-monad monad-transformers
我试图将以下有状态命令代码转换为Haskell.
while (true) {
while (get()) {
if (put1()) {
failImmediately();
}
}
if (put2()) {
succeedImmediately();
}
}
Run Code Online (Sandbox Code Playgroud)
无论是put1
和put2
读取系统的状态,并对其进行修改.get
可以简单地读取状态.failImmediately
应该突破无限循环并呈现一种结果,succeedImmediately
也应该突破却呈现出不同的结果.
我试图用是State Env Result
其中Env
代表环境的状态,Result
是像Either Failure Success
一些定制Failure
和Success
.
我挣扎着要求整个结果表达式应该崩溃到Failure
/ Success
一旦它们中的一个产生(打破循环),否则继续前进.
我有一个想法是利用Either Exit ()
地方data Exit = Success | Failure
和使用StateT
某种方式在表现Left
对的Either
,就好像Either
是被链接的单子,也就是忽略任何后续行动.
我真的很感激haskell代码的任何灵感或样本,它将实现与上面的代码片段相同的行为.
编辑:精炼版移动到一个单独的问题" 有不同类型的短路的状态计算(可能,或者) ".
使用来自@ chi答案的套件,只需突出显示您不需要全部功能ContT
,直接短路语义EitherT
就足够了:
import Control.Monad.Trans.Either
data Result a = Failure | Success a
foo :: EitherT (Result Int) IO Int
foo = forever $ do
whileM get $ do
whenM put1 $ do
left Failure
whenM put2 $ do
left $ Success 42
run :: (Monad m) => EitherT (Result a) m a -> m (Maybe a)
run act = do
res <- runEitherT act
return $ case res of
Left Failure -> Nothing
Left (Success x) -> Just x
Right x -> Just x
-- whenM / whileM and get/put1/put2 as per @chi's answeer
Run Code Online (Sandbox Code Playgroud)