# Contstuff

### From HaskellWiki

(Added lots and lots of stuff.) |
m (→Lifting: Adjusted to recent changes in the library.) |
||

(2 intermediate revisions by one user not shown) | |||

Line 1: | Line 1: | ||

− | |||

− | |||

The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''. | The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''. | ||

Line 56: | Line 54: | ||

<haskell> | <haskell> | ||

labelCC :: a -> ContT r m (a, Label (ContT r m) a) | labelCC :: a -> ContT r m (a, Label (ContT r m) a) | ||

− | goto :: Label (ContT r m) a -> a -> ContT r m | + | goto :: Label (ContT r m) a -> a -> ContT r m () |

</haskell> | </haskell> | ||

Line 80: | Line 78: | ||

<haskell> | <haskell> | ||

lift :: (Transformer t, Monad m) => m a -> t m a | lift :: (Transformer t, Monad m) => m a -> t m a | ||

− | base :: | + | base :: LiftBase m => Base m a -> m a |

− | io :: (Base m | + | io :: (LiftBase m, Base m ~ IO) => Base m a -> m a |

</haskell> | </haskell> | ||

## Latest revision as of 02:50, 1 October 2010

The contstuff library implements a number of monad transformers and monads, which make heavy use of continuation passing style (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use *contstuff*.

## Contents |

## [edit] 1 Basics

### [edit] 1.1 ContT

The *ContT* monad transformer is the simplest of all CPS-based monads:

`newtype ContT r m a`

It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With *ContT* you get an elegant encoding of computations, which support:

- abortion (premature termination),
- resumption (start a computation at a certain spot),
- branches (aka
*goto*), - result accumulation,
- etc.

*ContT*. If you don't use them, then

*ContT*behaves like the identity monad. A computation of type

*ContT*computation you can use

runContT :: (a -> m r) -> ContT r m a -> m r evalContT :: Applicative m => ContT r m r -> m r

### [edit] 1.2 Abortion

Let's have a look at a small example:

testComp1 :: ContT () IO () testComp1 = forever $ do txt <- io getLine case txt of "info" -> io $ putStrLn "This is a test computation." "quit" -> abort () _ -> return ()

*ContT*. First of all,

*ContT*is a monad transformer, so you can for example lift

*IO*actions to a CPS computation. The

*IO*monad. You can also use the more generic

*ContT*. Each

*ContT*subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The

### [edit] 1.3 Resumption and branches

You can capture the current continuation using the commonlabelCC :: a -> ContT r m (a, Label (ContT r m) a) goto :: Label (ContT r m) a -> a -> ContT r m ()

These slightly complicated looking functions are actually very simple to use:

testComp2 :: ContT r IO () testComp2 = do (i, again) <- labelCC 0 io (print i) when (i < 10) $ goto again (i+1) io (putStrLn $ "Final result: " ++ show i)

Labels are first class values in *contstuff*. This means you can carry them around. They are only limited in that they can't be carried outside of a *ContT* computation.

### [edit] 1.4 Lifting

As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:

lift :: (Transformer t, Monad m) => m a -> t m a base :: LiftBase m => Base m a -> m a io :: (LiftBase m, Base m ~ IO) => Base m a -> m a

*IO*.

### [edit] 1.5 Accumulating results

*ContT*does not require the underlying functor to be a monad. Whenever the underlying functor is an

testComp3 :: Num a => ContT r [] (a, a) testComp3 = do x <- pure 10 <|> pure 20 y <- pure (x+1) <|> pure (x-1) return (x, y)

*contstuff*library implements a convenience function

listA :: (Alternative f) => [a] -> f a

testComp3' :: Num a => ContT r [] (a, a) testComp3' = do x <- listA [10, 20] y <- listA [x+1, x-1] return (x, y)

testComp4 :: Num a => ContT (a, a) [] (a, a) testComp4 = do x <- listA [10, 20] when (x == 10) (abort (10, 10)) y <- listA [x+1, x-1] return (x, y)

## [edit] 2 State

The *contstuff* library also comes with a monad transformer for stateful computations. These computations carry state of a certain type and can access it at any time. It's called *StateT*, just like in other transformer libraries, but this one has very different semantics and also takes an additional parameter:

`newtype StateT r s m a`

It is basically a generalization of *ContT*. In fact you can use all the features of *ContT* in a *StateT* computation, too, including abortion, labels, accumulation, etc.

### [edit] 2.1 Accessing the state

There are many functions to access the implicit state. These don't belong to*StateT*directly, but instead to a type class called

*Stateful*, of which

*StateT*is an instance. The associated type

-- Where 'm' is a Stateful monad, 'StateOf m' is the type of its state. get :: (Stateful m) => m (StateOf m) put :: (Stateful m) => StateOf m -> m () putLazy :: (Stateful m) => StateOf m -> m () -- Convenience functions. getField :: (Functor m, Stateful m) => (StateOf m -> a) -> m a modify :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m () modifyLazy :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m () modifyField :: (Monad m, Stateful m) => (StateOf m -> a) -> (a -> StateOf m) -> m () modifyFieldLazy :: (Monad m, Stateful m) => (StateOf m -> a) -> (a -> StateOf m) -> m ()

*StateT*is strict by default. When setting a new state using

### [edit] 2.2 Running

To run a stateful computation you can use therunStateT :: s -> (s -> a -> m r) -> StateT r s m a -> m r evalStateT :: (Applicative m) => s -> StateT r s m r -> m r execStateT :: (Applicative m) => s -> StateT s s m a -> m s

## [edit] 3 Exceptions

*Contstuff* provides an *EitherT* monad transformer:

`newtype EitherT r e m a`

This monad transformer is a generalization of *ContT* in that it supports two continuations. The second one can be accessed indirectly by the various exception handling functions.

### [edit] 3.1 Raising and catching

There are a number of functions to handle exceptions, which belong to a class*EitherT*is an instance of this class.

-- Where 'm' is a monad supporting exceptions, 'Exception m' is the -- type of the exceptions. raise :: (HasExceptions m) => Exception m -> m a try :: (HasExceptions m) => m a -> m (Either (Exception m) a) -- Convenience functions. catch :: (HasExceptions m, Monad m) => m a -> (Exception m -> m a) -> m a handle :: (HasExceptions m, Monad m) => (Exception m -> m a) -> m a -> m a finally :: (HasExceptions m, Monad m) => m a -> m b -> m a bracket :: (HasExceptions m, Monad m) => m res -> (res -> m b) -> (res -> m a) -> m a bracket_ :: (HasExceptions m, Monad m) => m a -> m b -> m c -> m c

### [edit] 3.2 Running

To run an*EitherT*computation you can use the

*EitherT*computation. There is also a convenience function

*Either*value:

runEitherT :: (a -> m r) -> (e -> m r) -> EitherT r e m a -> m r evalEitherT :: (Applicative m) => EitherT (Either e a) e m a -> m (Either e a)

## [edit] 4 Choice/nondeterminism

The *ChoiceT* monad transformer is basically a list monad transformer and a proper one at that. It is also very fast, because choice is implemented as a CPS-based left fold function:

`newtype ChoiceT r i m a`

### [edit] 4.1 Running

You can run a*ChoiceT*computation by using the slightly scary

runChoiceT :: (i -> a -> (i -> m r) -> m r) -> i -> (i -> m r) -> ChoiceT r i m a -> m r

This function takes a folding function, a base element, a final continuation (the folding function uses CPS) and a *ChoiceT* computation. Of course in practice you mostly just want a list of results or the first result or something like that. Luckily there are two convenience functions to do just that:

findFirst :: (Alternative f, Applicative m) => ChoiceT (f a) (f a) m a -> m (f a) findAll :: (Alternative f, Applicative m) => ChoiceT (f a) (f a) m a -> m (f a)

maybeChoiceT :: Applicative m => ChoiceT (Maybe a) (Maybe a) m a -> m (Maybe a) listChoiceT :: Applicative m => ChoiceT [a] [a] m a -> m [a]

### [edit] 4.2 Convenience functions

Often you just want to encode a list of choices. For this you can use thelistA :: (Alternative f) => [a] -> f a

*ChoiceT*, but is much faster than

choice :: [a] -> ChoiceT r i m a