How do I break out of a loop in Haskell?

时光总嘲笑我的痴心妄想 提交于 2019-12-04 04:56:53
Daniel Fischer

Looks like a job for whileM_:

stdin () = whileM_ (lift . fmap not $ IO.hIsEOF IO.stdin) (lift getLine >>= respond)

or, using do-notation similarly to the original example:

stdin () =
    whileM_ (lift . fmap not $ IO.hIsEOF IO.stdin) $ do
        str <- lift getLine
        respond str

The monad-loops package offers also whileM which returns a list of intermediate results instead of ignoring the results of the repeated action, and other useful combinators.

I prefer the following:

import Control.Monad
import Control.Monad.Trans.Either   

loop :: (Monad m) => EitherT e m a -> m e
loop = liftM (either id id) . runEitherT . forever

-- I'd prefer 'break', but that's in the Prelude
quit :: (Monad m) => e -> EitherT e m r
quit = left

You use it like this:

import Pipes
import qualified System.IO as IO

stdin :: () -> Producer String IO ()
stdin () = loop $ do
    eof <- lift $ lift $ IO.hIsEOF IO.stdin
    if eof
    then quit ()
    else do
        str <- lift $ lift getLine
        lift $ respond str

See this blog post where I explain this technique.

The only reason I don't use that in the tutorial is that I consider it less beginner-friendly.

Since there is no implicit flow there is no such thing like "break". Moreover your sample already is small block which will be used in more complicated code.

If you want to stop "producing strings" it should be supported by your abstraction. I.e. some "managment" of "pipes" using special monad in Consumer and/or other monads that related with this one.

You can simply import System.Exit, and use exitWith ExitSuccess

Eg. if (input == 'q') then exitWith ExitSuccess else print 5 (anything)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!