Haskell “我该怎么做?”;“继续”;在“单子”循环中?

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> ..

在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>
    ...
表格[1..100]$\i->

a记住,在Haskell中这样的循环不是魔法……它们只是普通的一流东西,你可以自己编写

不管它值多少钱,我认为把
MaybeT
看作一个Monad转换器并不太有用。对我来说,
MaybeT
只是一个新类型的包装器,它提供了
(>>=)
的替代实现……就像你如何使用
产品
求和
第一次
,等等。来提供
mappend
mempty
的替代实现

现在,
(>>=)
为您提供的是
ioa->(a->iob)->iob
。但是让
(>>=)
在这里是
IO(可能是a)->(a->IO(可能是b)->IO(可能是b)
会更有用。一旦你得到第一个返回a
Nothing
的动作,就真的不可能再“绑定”了。这正是
可能给你的。你也会得到一个“自定义实例”对于
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]