Copyright | (c) Michael Szvetits 2020 |
---|---|
License | BSD3 (see the file LICENSE) |
Maintainer | typedbyte@qualified.name |
Stability | stable |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
This module provides TemplateHaskell
functions to generate the handling,
lifting and tagging infrastructure for effect type classes.
Synopsis
- makeEffect :: Name -> Q [Dec]
- makeHandler :: Name -> Q [Dec]
- makeLifter :: Name -> Q [Dec]
- makeTaggedEffect :: Name -> Q [Dec]
- makeTaggedEffectWith :: (String -> Q String) -> Name -> Q [Dec]
- makeTagger :: Name -> Q [Dec]
- makeTaggerWith :: (String -> Q String) -> Name -> Q [Dec]
- removeApostrophe :: String -> Q String
Common Generators
makeEffect :: Name -> Q [Dec] Source #
Generates the effect handling and lifting infrastructure for an effect which
does not have a tag type parameter. Requires the TemplateHaskell
language
extension.
Consider the following effect type class:
class Monad
m => MyEffect a b c m where
...
makeEffect ''MyEffect
then generates two instances for this effect type
class (Lift
for first-order effects, Control
for higher-order effects):
instanceHandle
(MyEffect a b c) t m => MyEffect a b c (Via
(MyEffect a b c) t m) where ... instance {-# OVERLAPPABLE #-}Lift
/Control
(MyEffect a b c) t m => MyEffect a b c (Via
eff t m) where ...
Without TemplateHaskell
, you have to write these instances by hand. These
two instances can also be generated separately, see makeHandler
and makeLifter
.
makeHandler :: Name -> Q [Dec] Source #
Similar to makeEffect
, but only generates the effect type class instance
for handling an effect.
makeLifter :: Name -> Q [Dec] Source #
Similar to makeEffect
, but only generates the effect type class instance
for lifting an effect.
Tag-based Generators
makeTaggedEffect :: Name -> Q [Dec] Source #
Generates the effect handling and lifting infrastructure for an effect which
has a tag type parameter. It is expected that the tag type parameter is the first
type parameter of the effect type class. It is also expected that the names of the
effect type class and its methods end with an apostrophe "'". If you want more
control over the naming convention, use makeTaggedEffectWith
.
In general, this function generates everything that makeEffect
does, but also some
additional things. Consider the following effect type class:
class Monad
m => MyEffect' tag a b c m where
methodA' :: a -> m ()
methodB' :: b -> m ()
methodC' :: c -> m ()
then generates the following additional things:makeTaggedEffect
''MyEffect'
- A type synonym for the untagged version of
MyEffect'
with the nameMyEffect
(note the missing apostrophe). - Untagged versions of the effect methods, namely
methodA
,methodB
andmethodC
(note the missing apostrophes). - An instance of
MyEffect'
for the typeTagger
which does not handle the effect, but simply tags, retags or untags theMyEffect'
constraint of a computation. - Three functions
tagMyEffect'
,retagMyEffect'
anduntagMyEffect'
which make use of theTagger
instance.
As a rule of thumb, whenever you see an apostrophe suffix in the name of a definition
somewhere in this library, it has something to do with tags. Most of the time you
will use such definitions in combination with the language extension TypeApplications
,
like:
... forall tag ... methodA' @tag ... tagMyEffect' @"newTag" program retagMyEffect' @"oldTag" @"newTag" program untagMyEffect' @"erasedTag" program
All the tag-related definitions can also be generated separately (i.e., without the
instances generated by makeEffect
), see makeTagger
and makeTaggerWith
.
makeTaggedEffectWith :: (String -> Q String) -> Name -> Q [Dec] Source #
Similar to makeTaggedEffect
, but allows to define a naming convention function
for the names of the effect type class and its methods. This function is used to
transform the name of a tagged definition (i.e., the type class or its methods) into
its untagged counterpart.
The default naming convention is enforced by removeApostrophe
, which simply
removes the apostrophe "'" at the end of a name.
makeTagger :: Name -> Q [Dec] Source #
Similar to makeTaggedEffect
, but only generates the tag-related definitions.
makeTaggerWith :: (String -> Q String) -> Name -> Q [Dec] Source #
Similar to makeTaggedEffectWith
, but only generates the tag-related definitions.