HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulefree-5.2Haskell2010

Control.Monad.Trans.Iter

Based on Capretta's Iterative Monad Transformer

Unlike Free, this is a true monad transformer.

  • 2 types
  • 1 class
  • 13 values
  • Packagefree-5.2
  • Exports16
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceIter.hs

Functions in Haskell are meant to be pure. For example, if an expression has type Int, there should exist a value of the type such that the expression can be replaced by that value in any context without changing the meaning of the program.

Some computations may perform side effects (unsafePerformIO), throw an exception (using error); or not terminate (let infinity = 1 + infinity in infinity).

While the IO monad encapsulates side-effects, and the Either monad encapsulates errors, the Iter monad encapsulates non-termination. The IterT transformer generalizes non-termination to any monadic computation.

Computations in IterT (or Iter) can be composed in two ways:

  • Sequential: Using the Monad instance, the result of a computation can be fed into the next.

  • Parallel: Using the MonadPlus instance, several computations can be executed concurrently, and the first to finish will prevail. See also the cabbage example.

The iterative monad transformer

1 declaration
newtypenewtype IterT (m :: Type -> Type) a
#

The monad supporting iteration based over a base monad m.

IterT ~ FreeT Identity

Constructors

Instances34MonadTrans, MonadError, MonadReader, MonadState, MonadWriter, MonadFree, …

Capretta's iterative monad

3 declarations
valueiter :: Either a (Iter a) -> Iter a
#

Builds an iterative computation from one first step.

Property
runIter . iter == id
valuerunIter :: Iter a -> Either a (Iter a)
#

Executes the first step of an iterative computation

Property
iter . runIter == id

Combinators

8 declarations
valuedelay :: (Monad f, MonadFree f m) => m a -> m a
#

Adds an extra layer to a free monad value.

In particular, for the iterative monad Iter, this makes the computation require one more step, without changing its final result.

Property
runIter (delay ma) == Right ma
valuecutoff :: Monad m => Integer -> IterT m a -> IterT m (Maybe a)
#

Cuts off an iterative computation after a given number of steps. If the number of steps is 0 or less, no computation nor monadic effects will take place.

The step where the final value is produced also counts towards the limit.

Some examples (n ≥ 0):

cutoff 0     _        ≡ return Nothing
cutoff (n+1) . return ≡ return . Just
cutoff (n+1) . lift   ≡ lift . liftM Just
cutoff (n+1) . delay  ≡ delay . cutoff n
cutoff n     never    ≡ iterate delay (return Nothing) !! n

Calling retract . cutoff n is always terminating, provided each of the steps in the iteration is terminating.

valueuntilJust :: Monad m => m (Maybe a) -> IterT m a
#

Repeatedly run a computation until it produces a Just value. This can be useful when paired with a monad that has side effects.

For example, we may have genId :: IO (Maybe Id) that uses a random number generator to allocate ids, but fails if it finds a collision. We can repeatedly run this with

retract (untilJust genId) :: IO Id
valueinterleave :: Monad m => [IterT m a] -> IterT m [a]
#

Interleaves the steps of a finite list of iterative computations, and collects their results.

The resulting computation has as many steps as the longest computation in the list.

valueinterleave_ :: Monad m => [IterT m a] -> IterT m ()
#

Interleaves the steps of a finite list of computations, and discards their results.

The resulting computation has as many steps as the longest computation in the list.

Equivalent to void . interleave.

Consuming iterative monads

3 declarations

IterT ~ FreeT Identity

1 declaration
classclass Monad m => MonadFree (f :: Type -> Type) (m :: Type -> Type) | m -> f where
#

Monads provide substitution (fmap) and renormalization (join):

m >>= f = join (fmap f m)

A free Monad is one that does no work during the normalization step beyond simply grafting the two monadic values together.

[] is not a free Monad (in this sense) because join [[a]] smashes the lists flat.

On the other hand, consider:

data Tree a = Bin (Tree a) (Tree a) | Tip a
instance Monad Tree where
  return = Tip
  Tip a >>= f = f a
  Bin l r >>= f = Bin (l >>= f) (r >>= f)

This Monad is the free Monad of Pair:

data Pair a = Pair a a

And we could make an instance of MonadFree for it directly:

instance MonadFree Pair Tree where
   wrap (Pair l r) = Bin l r

Or we could choose to program with Free Pair instead of Tree and thereby avoid having to define our own Monad instance.

Moreover, Control.Monad.Free.Church provides a MonadFree instance that can improve the asymptotic complexity of code that constructs free monads by effectively reassociating the use of (>>=). You may also want to take a look at the kan-extensions package (http://hackage.haskell.org/package/kan-extensions).

See Free for a more formal definition of the free Monad for a Functor.

Methods

  • wrap :: f (m a) -> m a

    Add a layer.

    wrap (fmap f x) ≡ wrap (fmap return x) >>= f
    
Instances18MonadFree, …

Examples

0 declarations