moo-nad-0.1.0.1: lib-example-impl/Moo.hs
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeSynonymInstances #-}
-- | This is the implementation module for the signature of the same name.
module Moo (module Moo, runReaderT) where
import Data.Kind
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader
import Control.Monad.Dep.Has
type M = ReaderT EnvIO IO
type E = EnvIO
type D = IO
liftD :: D x -> M x
liftD = lift
-- | Same definition as the one in the module signature.
class HasLogger d e | e -> d where
logger :: e -> Int -> String -> d ()
-- | Same definition as the one in the module signature.
data Counter d = Counter {
askCounter :: d Int,
incCounter :: Int -> d ()
}
-- | This is the point at which we define a concrete type for the environment.
--
-- The 'HasLogger' instance is backed by a bare function defined at the top
-- level, while the 'Counter' component is a field by itself.
data EnvIO = EnvIO {
_logger :: Int -> String -> IO (),
_counter :: Counter IO
}
instance HasLogger D E where
logger (EnvIO {_logger}) = _logger
-- | 'Control.Monad.Dep.Has' establishes a relationship between the environment 'E',
-- the nominal record defining a component, and the effect monad the component
-- uses in the environment..
instance Has Counter D E where
dep (EnvIO {_counter}) = _counter