打破循环
Breaking the loop
我有以下代码示例:
data Smth = A | B
data MyError = MkMyError
data MyState = MkMyState
run :: [Smth] -> Either MyError (Maybe Integer)
run param =
evalState
( foldM
( \acc a -> do
res <- go a
case res of
Right (Just _) -> undefined -- I want to break here when Right value is Just
_ -> return (acc >> res)
)
(Right Nothing)
param
)
MkMyState
where
go :: Smth -> State MyState (Either MyError (Maybe Integer))
go = undefined
我有按顺序处理的 Smth
列表,它们根据 State
monad 中的状态和 Smth
值处理结果。
我想在 go
结果为 MyError
时插入 run
(Either
的左值)。
这适用于使用 >>
运算符的代码片段。
但是,我也想有可能在 go
函数结果为 Right (Just _)
时中断折叠(行中有注释)。
问题
当我得到 Just
值时如何打破下面的循环?
我想在两种情况下打破循环:
- 如果出现错误 -
go
导致 Left
值
- 在
Just
值的情况下 - go
导致 Right (Just _)
值。这是 Maybe
monad 和 >>
运算符的某种翻转行为。我不想在 Nothing
上中断,而是在 Just
. 上中断
这是怎么编的?
只要 go
不断返回 Right Nothing
并在第一个 go
调用结果时停止,我是否正确认为您只想处理 Smth
在 Left _
或 Right (Just _)
中没有 运行ning 任何更多 go
电话?
如果是这样,我认为您的 foldM
在这里没有任何意义。如果出现错误或 Just
,您想立即停止,但 foldM
只是在错误或 Just
之后继续处理 Smth
s。 acc >> res
确保折叠最终 returns 第一个错误的值,但您仍然处理所有 Smth
s(或 运行 永远,如果输入列表是无限的)。
相反,您需要 process
:
run :: [Smth] -> Either MyError (Maybe Integer)
run param = evalState (process param) MkMyState
where
process :: [Smth] -> State MyState (Either MyError (Maybe Integer))
process (a:as) = do
res <- go a
case res of
Right Nothing -> process as
_ -> return res -- stop on Left _ or Right (Just _)
process [] = return $ Right Nothing
go :: Smth -> State MyState (Either MyError (Maybe Integer))
go = undefined
如果你真的想把 process
写成折叠,你可以,虽然它只是一个 foldr
,而不是 foldM
:
process :: [Smth] -> State MyState (Either MyError (Maybe Integer))
process = foldr step (return $ Right Nothing)
where step a acc = do
res <- go a
case res of
Right Nothing -> acc
_ -> return res
我有以下代码示例:
data Smth = A | B
data MyError = MkMyError
data MyState = MkMyState
run :: [Smth] -> Either MyError (Maybe Integer)
run param =
evalState
( foldM
( \acc a -> do
res <- go a
case res of
Right (Just _) -> undefined -- I want to break here when Right value is Just
_ -> return (acc >> res)
)
(Right Nothing)
param
)
MkMyState
where
go :: Smth -> State MyState (Either MyError (Maybe Integer))
go = undefined
我有按顺序处理的 Smth
列表,它们根据 State
monad 中的状态和 Smth
值处理结果。
我想在 go
结果为 MyError
时插入 run
(Either
的左值)。
这适用于使用 >>
运算符的代码片段。
但是,我也想有可能在 go
函数结果为 Right (Just _)
时中断折叠(行中有注释)。
问题
当我得到 Just
值时如何打破下面的循环?
我想在两种情况下打破循环:
- 如果出现错误 -
go
导致Left
值 - 在
Just
值的情况下 -go
导致Right (Just _)
值。这是Maybe
monad 和>>
运算符的某种翻转行为。我不想在Nothing
上中断,而是在Just
. 上中断
这是怎么编的?
只要 go
不断返回 Right Nothing
并在第一个 go
调用结果时停止,我是否正确认为您只想处理 Smth
在 Left _
或 Right (Just _)
中没有 运行ning 任何更多 go
电话?
如果是这样,我认为您的 foldM
在这里没有任何意义。如果出现错误或 Just
,您想立即停止,但 foldM
只是在错误或 Just
之后继续处理 Smth
s。 acc >> res
确保折叠最终 returns 第一个错误的值,但您仍然处理所有 Smth
s(或 运行 永远,如果输入列表是无限的)。
相反,您需要 process
:
run :: [Smth] -> Either MyError (Maybe Integer)
run param = evalState (process param) MkMyState
where
process :: [Smth] -> State MyState (Either MyError (Maybe Integer))
process (a:as) = do
res <- go a
case res of
Right Nothing -> process as
_ -> return res -- stop on Left _ or Right (Just _)
process [] = return $ Right Nothing
go :: Smth -> State MyState (Either MyError (Maybe Integer))
go = undefined
如果你真的想把 process
写成折叠,你可以,虽然它只是一个 foldr
,而不是 foldM
:
process :: [Smth] -> State MyState (Either MyError (Maybe Integer))
process = foldr step (return $ Right Nothing)
where step a acc = do
res <- go a
case res of
Right Nothing -> acc
_ -> return res