ether-0.2.1.0: src/Control/Ether/Abbr.hs
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
-- | Abbreviations for constraints.
module Control.Ether.Abbr
( type (-->)
, type (<--)
, type (<->)
, type (-!-)
, Ether
, ReifyAbbr
) where
import GHC.Exts (Constraint)
import Control.Monad.Ether
-- | Turns an abbreviation into an actual constraint.
type family ReifyAbbr (abbr :: *) (m :: * -> *) :: Constraint
-- | Denotes 'MonadReader'. The mnemonic is that you read values of type @r@
-- from the reader environment tagged by @tag@, thus the arrows points
-- from @tag@ to @r@.
data tag --> r
type instance ReifyAbbr (tag --> r) m = MonadReader tag r m
-- | Denotes 'MonadWriter'. The mnemonic is that you write values of @w@
-- to the writer accumulator tagged by @tag@, thus the arrows points
-- from @w@ to @tag@.
data tag <-- w
type instance ReifyAbbr (tag <-- w) m = MonadWriter tag w m
-- | Denotes 'MonadState'. The mnemonic is that you can both read from and
-- write into the state, thus the arrow points in both directions.
data tag <-> s
type instance ReifyAbbr (tag <-> s) m = MonadState tag s m
-- | Denotes 'MonadExcept'.
data tag -!- e
type instance ReifyAbbr (tag -!- e) m = MonadExcept tag e m
-- | Reify a list of constraint abbreviations.
--
-- > f :: Ether '[Foo --> r, Bar <-- w, Baz <-> s, Quux -!- e] m => m a
--
-- expands into
--
-- > f :: ( MonadReader Foo r m
-- > , MonadWriter Bar w m
-- > , MonadState Baz s m
-- > , MonadExcept Quux e m
-- > ) => m a
type family Ether (abbrs :: [*]) m :: Constraint where
Ether '[] m = ()
Ether (abbr ': abbrs) m = (ReifyAbbr abbr m, Ether abbrs m)