Haskell “我该怎么做?”;“继续”;在“单子”循环中?
在Haskell中,我经常发现自己需要跳过其余的迭代(如C中的Haskell “我该怎么做?”;“继续”;在“单子”循环中?,haskell,Haskell,在Haskell中,我经常发现自己需要跳过其余的迭代(如C中的continue): forM_ [1..100] $ \ i -> a <- doSomeIO when (not $ isValid1 a) <skip_rest_of_the_iteration> b <- doSomeOtherIO a when (not $ isValid2 b) <skip_rest_of_the_iteration> ..
continue
):
forM_ [1..100] $ \ i ->
a <- doSomeIO
when (not $ isValid1 a) <skip_rest_of_the_iteration>
b <- doSomeOtherIO a
when (not $ isValid2 b) <skip_rest_of_the_iteration>
...
表格[1..100]$\i->
a记住,在Haskell中这样的循环不是魔法……它们只是普通的一流东西,你可以自己编写
不管它值多少钱,我认为把MaybeT
看作一个Monad转换器并不太有用。对我来说,MaybeT
只是一个新类型的包装器,它提供了(>>=)
的替代实现……就像你如何使用产品
,求和
,第一次
,和
,等等。来提供mappend
和mempty
的替代实现
现在,(>>=)
为您提供的是ioa->(a->iob)->iob
。但是让(>>=)
在这里是IO(可能是a)->(a->IO(可能是b)->IO(可能是b)
会更有用。一旦你得到第一个返回aNothing
的动作,就真的不可能再“绑定”了。这正是可能给你的。你也会得到一个“自定义实例”对于guard
,guard::Bool->IO(可能是a)
,而不是guard::IO a
forM_ [1..100] $ \i -> runMaybeT $ do
a <- lift doSomeIO
guard (isValid1 a)
b <- lift $ doSomeOtherIO a
guard (isValid2 b)
...
表单[1..100]$\i->runMaybeT$do
如果你想循环一个列表或其他容器来执行动作和/或产生一个汇总值,你会发现通常的便利工具,如<代码> Fuy和 FLDMM/COD>对这个工作来说不够好,你可能想考虑<代码> FordDR < /Cord>,这对工作来说是足够强大的。在容器上,您可以使用普通的旧递归或拉入类似https://hackage.haskell.org/package/loops
或(用于非常不同的口味)https://hackage.haskell.org/package/machines
或者https://hackage.haskell.org/package/pipes
以下是使用裸体递归的方法:
loop [] = return () -- done with the loop
loop (x:xs) =
do a <- doSomeIO
if ...a...
then return () -- exit the loop
else do -- continuing with the loop
b <- doSomeMoreIO
if ...b...
then return () -- exit the loop
else do -- continuing with the loop
...
loop xs -- perform the next iteration
您可以使用控件中的when
函数稍微整理一下。Monad:
loop [] = return ()
loop (x:xs) =
do a <- doSomeIO
when (not ...a...) $ do
b <- doSomeMoreIO
when (not ...b...) $ do
...
loop xs
有一些关于Hackage的软件包提供各种各样的循环。我见过的最有趣的可能是Monad transformers从来都不是必需的——只是方便而已。谢谢你的回答。但是,也许我没有说清楚(我正在编辑我的问题),但我想要的不是中断
,而是继续
。有一个微妙的区别——我想跳过迭代的其余部分,而不是整个循环。我已经改变了问题。谢谢。我正在尝试循环
,但我无法让中断
工作。你能看看吗?
loop [] = return ()
loop (x:xs) =
do a <- doSomeIO
when (not ...a...) $ do
b <- doSomeMoreIO
when (not ...b...) $ do
...
loop xs
import Control.Monad
loop [] = return ()
loop (x:xs) = do
putStrLn $ "x = " ++ show x
a <- getLine
when (a /= "stop") $ do
b <- getLine
when (b /= "stop") $ do
print $ "iteration: " ++ show x ++ ": a = " ++ a ++ " b = " ++ b
loop xs
main = loop [1..3]