如何在包中使用`break_`"循环"?

时间:2015-10-03 02:49:56

标签: loops haskell break

查看包loops,我发现它非常有趣并且可能有用。但是,关于包装的一部分我不明白:我应该如何使用break_

我们假设我有一个函数get' :: IO (Maybe Int),每次调用都会返回一个从文件中读取的数字,如果达到了EOF,则返回Nothing。我试图构建一个简单的循环,我打印每个数字并打破EOF。

现在,我知道无限循环我可以使用forever

import Control.Monad.Loop as ML
import Control.Monad as M

main = do
    M.sequence . loop $ do
        ML.forever
        return $ do
            mx <- get'
            case mx of
                Nothing -> ???
                Just x  -> print x

但我在哪里放break_?它是LoopT IO Int,所以我只能把它放在LoopT monad中,但它不应该被称为中间交互,而不是在定义循环时?这真让我困惑。

2 个答案:

答案 0 :(得分:4)

LoopT是monad transfomer,因此您需要liftIO print x声明。

以下是一些使用示例:

import Control.Monad 
import Control.Monad.Trans (liftIO)
import Control.Monad.Loop as ML

-- infinite printing loop
foo :: LoopT IO ()
foo = do
  x <- ML.iterate 0 (+1) 
  liftIO $ print x

run_foo = ML.exec_ foo

-- prints 1, 3, 5, 7, 9
bar :: IO () 
bar = ML.exec_ $ do
  x <- ML.iterate 1 (+2)
  if x < 10
    then liftIO $ print x
    else break_

<强>更新

如果你想在另一个monad中执行无限循环,我只会使用forever中的Control.Monad -

import Control.Monad
import Control.Monad.State

myloop = forever $ do
  x <- get
  liftIO $ print x
  put (x+1)

main = runStateT myloop 10 -- start loop at 10

更新2

另一个使用monadic条件的例子:

findFavoriteNumber = ML.exec_ $ do
  x <- ML.iterate 1 (+1)
  yn <- liftIO $ do putStr $ "is " ++ show x ++ " your favorite number? "
                    getLine
  if yn == "yes"
    then break_
    else return ()

当然,这个循环并没有返回最喜欢的数字 - 它只是一直询问,直到用户回答&#34;是&#34;。

答案 1 :(得分:2)

这是您的循环直接转换为loops样式:

module Main where
import Control.Monad.Loop as ML
import Text.Read (readMaybe)
import Control.Exception
import System.IO.Error
import Control.Applicative
import Control.Monad.IO.Class

get' :: IO (Maybe Int)
get' = do
  catchJust (\e -> if isEOFError e then Just () else Nothing)
            (return . readMaybe =<< getLine)
            (const $ return Nothing)

main :: IO ()
main = exec_ $
  ML.forever >> do
    mx <- liftIO get'
    case mx of
      Nothing -> break_
      Just x -> liftIO (print x)