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.Free.TH

Automatic generation of free monadic actions.

  • 4 values
  • Packagefree-5.2
  • Exports4
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceTH.hs

Free monadic actions

4 declarations
valuemakeFree :: Name -> Q [Dec]
#

$(makeFree ''T) provides free monadic actions for the constructors of the given data type T.

valuemakeFree_ :: Name -> Q [Dec]
#

Like makeFree, but does not provide type signatures. This can be used to attach Haddock comments to individual arguments for each generated function.

data LangF x = Output String x

makeFree_ 'LangF

-- | Output a string.
output :: MonadFree LangF m =>
          String   -- ^ String to output.
       -> m ()     -- ^ No result.

makeFree_ must be called *before* the explicit type signatures.

valuemakeFreeCon :: Name -> Q [Dec]
#

$(makeFreeCon 'Con) provides free monadic action for a data constructor Con. Note that you can attach Haddock comment to the generated function by placing it before the top-level invocation of makeFreeCon:

-- | Output a string.
makeFreeCon 'Output
valuemakeFreeCon_ :: Name -> Q [Dec]
#

Like makeFreeCon, but does not provide a type signature. This can be used to attach Haddock comments to individual arguments.

data LangF x = Output String x

makeFreeCon_ 'Output

-- | Output a string.
output :: MonadFree LangF m =>
          String   -- ^ String to output.
       -> m ()     -- ^ No result.

makeFreeCon_ must be called *before* the explicit type signature.

Documentation

0 declarations

To generate free monadic actions from a Type, it must be a data declaration (maybe GADT) with at least one free variable. For each constructor of the type, a new function will be declared.

Consider the following generalized definitions:

data Type a1 a2 … aN param = …
                           | FooBar t1 t2 t3 … tJ
                           | (:+) t1 t2 t3 … tJ
                           | t1 :* t2
                           | t1 `Bar` t2
                           | Baz { x :: t1, y :: t2, …, z :: tJ }
                           | forall b1 b2 … bN. cxt => Qux t1 t2 … tJ
                           | …

where each of the constructor arguments t1, …, tJ is either:

  1. A type, perhaps depending on some of the a1, …, aN.

  2. A type dependent on param, of the form s1 -> … -> sM -> param, M ≥ 0. At most 2 of the t1, …, tJ may be of this form. And, out of these two, at most 1 of them may have M == 0; that is, be of the form param.

For each constructor, a function will be generated. First, the name of the function is derived from the name of the constructor:

  • For prefix constructors, the name of the constructor with the first letter in lowercase (e.g. FooBar turns into fooBar).

  • For infix constructors, the name of the constructor with the first character (a colon :), removed (e.g. :+ turns into +).

Then, the type of the function is derived from the arguments to the constructor:

…
fooBar :: (MonadFree Type m) => t1' -> … -> tK' -> m ret
(+)    :: (MonadFree Type m) => t1' -> … -> tK' -> m ret
bar    :: (MonadFree Type m) => t1  -> … -> tK' -> m ret
baz    :: (MonadFree Type m) => t1' -> … -> tK' -> m ret
qux    :: (MonadFree Type m, cxt) => t1' -> … -> tK' -> m ret
…

The t1', …, tK' are those t1 … tJ that only depend on the a1, …, aN.

The type ret depends on those constructor arguments that reference the param type variable:

  1. If no arguments to the constructor depend on param, ret ≡ a, where a is a fresh type variable.

  2. If only one argument in the constructor depends on param, then ret ≡ (s1, …, sM). In particular, if M == 0, then ret ≡ (); if M == 1, ret ≡ s1.

  3. If two arguments depend on param, (e.g. u1 -> … -> uL -> param and v1 -> … -> vM -> param, then ret ≡ Either (u1, …, uL) (v1, …, vM).

Note that Either a () and Either () a are both isomorphic to Maybe a. Because of this, when L == 0 or M == 0 in case 3., the type of ret is simplified:

  • ret ≡ Either (u1, …, uL) () is rewritten to ret ≡ Maybe (u1, …, uL).

  • ret ≡ Either () (v1, …, vM) is rewritten to ret ≡ Maybe (v1, …, vM).

Examples

0 declarations

Teletype (regular data type declaration)

Retry (GADT declaration)