packages feed

moo-nad-0.1.0.1: lib-example-logic-that-logs/Moo.hsig

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
-- | The logic in this sub-library needs to know how to perform logging,
-- and use a counter
-- 
-- To allow for that, we expand the signature through signature merging, 
-- defining a 'HasLogger' typeclass and demanding that the environment 'E'
-- has an instance.
--
-- We also define a 'Counter' component (basically a record-of-functions polymorphic on 
-- the base monad) and tie it to the environment 'E' using the generic Has class from 
-- Control.Monad.Dep.Has.
signature Moo where

import Data.Kind
import Control.Monad.Dep.Has

data D :: Type -> Type  
data E :: Type  
instance HasLogger D E -- this wasn't in the base Moo signature
instance Has Counter D E -- this wasn't, either

-- A typeclass for extracting some capability from an environment.
--
-- Program logic invokes should invoke its method using "Moo.Prelude.self".
--
-- Typeclass definitions are allowed in signatures,
-- methods and all. The corresponding definitions in the implementation
-- modules must match exactly.
--
-- The typeclass could also have been imported from another package.
class HasLogger d e | e -> d where
    logger :: e -> Int -> String -> d ()

-- A component is a record-of-functions parameterized by the effect monad 
-- used by the functions.
--
-- Components are tied to the environment using the "Control.Monad.Dep.Has.Has" typeclass,
-- and program logic should invoke their functions using "Moo.Prelude.call".
--
-- Datatype definitions are allowed in signatures. The corresponding definitions in
-- the implementation modules must match exactly.
--
-- The datatype could also have been imported from another package.
data Counter d = Counter { 
        askCounter :: d Int,
        incCounter :: Int -> d ()
    }