有状态循环与不同类型的休息 [英] Stateful loop with different types of breaks
问题描述
while(true){
while (get()){
if(put1()){
failImmediately();
if(put2()){
succeedImmediately();
我尝试使用的是 我需要整体结果表达式应该在它们中的一个被生成(打破循环)并且以其他方式继续前进时折叠成 我的一个想法是使用 我真的很感激任何灵感或Haskell代码样本,它们可以达到与上面代码片段相同的行为。 编辑:精炼版本已移动到一个单独的问题有状态的计算与不同类型的短-circuit(Maybe,Either)。 使用@ chi的答案套件,只是强调你不需要 I am trying to convert the following stateful imperative code into Haskell. Both the What I tried to use was I struggle with the requirement that the whole resulting expression should collapse into the One idea I had was use I would really appreciate any inspiration or sample of haskell code that would achieve the same behaviour as the snippet above. Edit: refined version moved to a separate question "Stateful computation with different types of short-circuit (Maybe, Either)". Using the kit from @chi's answer, just highlighting that you don't need the full power of
这篇关于有状态循环与不同类型的休息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! put1
和
put2
读取系统状态并修改它。 get
可以简单地只读状态。 failImmediately
应该跳出无限循环并提供一种类型的结果, succeedImmediately
也应该突破,不同的结果。
State Env Result
其中 Env code>表示环境状态,
或者失败成功
对于某些自定义失败
和成功
。
失败
/ 成功
。
Exit()
其中数据Exit = Success |失败
并使用 StateT
以某种方式在的
Left
或者就好像或者
是被链接的monad,即忽略任何后续动作。
ContT
的全部功能, EitherT
就足够了:
import Control.Monad .Trans.Eithe r
数据结果a =失败|成功a
foo :: EitherT(Result Int)IO Int
foo =永远$ do
whileM获得$ do
whenM put1 $ do
还剩失败
whenM put2 $ do
left $成功42
run ::(Monad m)=>或者T(结果a)m a - > m(可能是a)
run act = do
res< - runEitherT act
return $ case res
Left Failure - > Nothing
Left(Success x) - >只需x
Right x - >只需x
- 当M / whileM和get / put1 / put2根据@ chi的回答时
while (true) {
while (get()) {
if (put1()) {
failImmediately();
}
}
if (put2()) {
succeedImmediately();
}
}
put1
and put2
read a state of the system and modify it. get
can for simplicity just read the state. failImmediately
should break out of the endless-loop and present one type of result, succeedImmediately
should also break out but present a different result.State Env Result
where Env
represented the state of environment and Result
was something like Either Failure Success
for some custom Failure
and Success
.Failure
/Success
once one of them is produced (breaking the loop) and otherwise keep going.Either Exit ()
where data Exit = Success | Failure
and use StateT
somehow to behave upon Left
of the Either
as if Either
was the monad being chained, i.e. ignoring any subsequent actions.ContT
, the direct-short-circuiting semantics of EitherT
is enough: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