control-monad-loop-0.1: Simple monad transformer for imperative-style loops

Copyright | (c) Joseph Adams 2012
License | BSD3
Maintainer | joeyadams3.14159@gmail.com
Safe Haskell | Safe-Inferred
Language | Haskell98

Control.Monad.Trans.Loop

Contents

- The LoopT monad transformer
- continue and exit
- Looping constructs
- Lifting other operations

Description

Synopsis

- newtype LoopT c e (m :: Type -> Type) a = LoopT {
  - runLoopT :: forall r. (c -> m r) -> (e -> m r) -> (a -> m r) -> m r
  }
- stepLoopT :: Monad m => LoopT c e m c -> (c -> m e) -> m e
- continue :: forall e (m :: Type -> Type) a. LoopT () e m a
- exit :: forall c (m :: Type -> Type) a. LoopT c () m a
- continueWith :: forall c e (m :: Type -> Type) a. c -> LoopT c e m a
- exitWith :: forall e c (m :: Type -> Type) a. e -> LoopT c e m a
- foreach :: Monad m => [a] -> (a -> LoopT c () m c) -> m ()
- while :: Monad m => m Bool -> LoopT c () m c -> m ()
- doWhile :: Monad m => LoopT a a m a -> m Bool -> m a
- once :: Monad m => LoopT a a m a -> m a
- repeatLoopT :: Monad m => LoopT c e m a -> m e
- iterateLoopT :: Monad m => c -> (c -> LoopT c e m c) -> m e
- liftLocalLoopT :: Monad m => (forall a. m a -> m a) -> LoopT c e m b -> LoopT c e m b

# The LoopT monad transformer

newtype LoopT c e (m :: Type -> Type) a Source #

`LoopT` is a monad transformer for the loop body. It provides two capabilities:

- `continue` to the next iteration.
- `exit` the whole loop.

Constructors

LoopT |

Fields

- runLoopT :: forall r. (c -> m r) -> (e -> m r) -> (a -> m r) -> m r

#### Instances

Instances details

MonadBase b m => MonadBase b (LoopT c e m) Source # |
Instance details Defined in Control.Monad.Trans.Loop Methods liftBase :: b α -> LoopT c e m α Source #
MonadTrans (LoopT c e) Source # |
Instance details Defined in Control.Monad.Trans.Loop Methods lift :: Monad m => m a -> LoopT c e m a Source #
MonadIO m => MonadIO (LoopT c e m) Source # |
Instance details Defined in Control.Monad.Trans.Loop Methods liftIO :: IO a -> LoopT c e m a Source #
Applicative (LoopT c e m) Source # |
Instance details Defined in Control.Monad.Trans.Loop Methods pure :: a -> LoopT c e m a Source # (<*>) :: LoopT c e m (a -> b) -> LoopT c e m a -> LoopT c e m b Source # liftA2 :: (a -> b -> c0) -> LoopT c e m a -> LoopT c e m b -> LoopT c e m c0 Source # (*>) :: LoopT c e m a -> LoopT c e m b -> LoopT c e m b Source # (<*) :: LoopT c e m a -> LoopT c e m b -> LoopT c e m a Source #
Functor (LoopT c e m) Source # |
Instance details Defined in Control.Monad.Trans.Loop Methods fmap :: (a -> b) -> LoopT c e m a -> LoopT c e m b Source # (<$) :: a -> LoopT c e m b -> LoopT c e m a Source #
Monad (LoopT c e m) Source # |
Instance details Defined in Control.Monad.Trans.Loop Methods (>>=) :: LoopT c e m a -> (a -> LoopT c e m b) -> LoopT c e m b Source # (>>) :: LoopT c e m a -> LoopT c e m b -> LoopT c e m b Source # return :: a -> LoopT c e m a Source #

stepLoopT :: Monad m => LoopT c e m c -> (c -> m e) -> m e Source #

Call a loop body, passing it a continuation for the next iteration. This can be used to construct custom looping constructs. For example, here is the definition of `foreach`:

    foreach list body = loop list
      where loop []     = return ()
            loop (x:xs) = stepLoopT (body x) (\_ -> loop xs)

# continue and exit

continue :: forall e (m :: Type -> Type) a. LoopT () e m a Source #

Skip the rest of the loop body and go to the next iteration.

exit :: forall c (m :: Type -> Type) a. LoopT c () m a Source #

Break out of the loop entirely.

continueWith :: forall c e (m :: Type -> Type) a. c -> LoopT c e m a Source #

Like `continue`, but return a value from the loop body.

exitWith :: forall e c (m :: Type -> Type) a. e -> LoopT c e m a Source #

Like `exit`, but return a value from the loop as a whole. See the documentation of `iterateLoopT` for an example.

# Looping constructs

foreach :: Monad m => [a] -> (a -> LoopT c () m c) -> m () Source #

Call the loop body with each item in the list.

If you do not need to `continue` or `exit` the loop, consider using `forM_` instead.

while :: Monad m => m Bool -> LoopT c () m c -> m () Source #

Repeat the loop body while the predicate holds. Like a `while` loop in C, the condition is tested first.

doWhile :: Monad m => LoopT a a m a -> m Bool -> m a Source #

Like a `do while` loop in C, where the condition is tested after the loop body.

`doWhile` returns the result of the last iteration. This is possible because, unlike `foreach` and `while`, the loop body is guaranteed to be executed at least once.

once :: Monad m => LoopT a a m a -> m a Source #

Execute the loop body once. This is a convenient way to introduce early exit support to a block of code.

`continue` and `exit` do the same thing inside of `once`.

repeatLoopT :: Monad m => LoopT c e m a -> m e Source #

Execute the loop body again and again. The only way to exit `repeatLoopT` is to call `exit` or `exitWith`.

iterateLoopT :: Monad m => c -> (c -> LoopT c e m c) -> m e Source #

Call the loop body again and again, passing it the result of the previous iteration each time around. The only way to exit `iterateLoopT` is to call `exit` or `exitWith`.

Example:

    count :: Int -> IO Int
    count n = iterateLoopT 0 $ \i ->
        if i < n
            then do
                lift $ print i
                return $ i+1
            else exitWith i

# Lifting other operations

liftLocalLoopT :: Monad m => (forall a. m a -> m a) -> LoopT c e m b -> LoopT c e m b Source #

Lift a function like `local` or `mask_`.