packages feed

registry-0.6.3.3: test/Test/Data/Registry/THSpec.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}

module Test.Data.Registry.THSpec where

import Data.Generics.Product.Typed
import Data.Registry.TH
import Protolude

-- * Example of TemplateHaskell usage to create the typeclass corresponding to a component

-- | We define 2 low-level components: Logger and Tracer
--   We make the corresponding typeclasses
data Logger m = Logger
  { -- a function taking 2 arguments
    _info :: Text -> Text -> m (),
    -- a function having a constraint
    _error :: forall a. (Monoid a) => a -> Text -> m ()
  }

makeTypeclass ''Logger

newtype Tracer m = Tracer
  { _traceIt :: Text -> m ()
  }

makeTypeclass ''Tracer

-- | Now we make a component which is going to use both components
newtype Service m = Service
  { doIt :: Int -> Text -> m ()
  }

newService :: Monad m => Logger m -> Tracer m -> Service m
newService logger tracer =
  Service
    { doIt = \n t -> run (implementService n t)
    }
  where
    -- the typeclass instances can be resolved by using a Reader containing
    --  a tuple with all the components
    run = flip runReaderT (logger, tracer)

-- | Implement the service using typeclasses
implementService ::
  Monad m =>
  WithLogger m =>
  WithTracer m =>
  Int ->
  Text ->
  m ()
implementService n t = do
  info "doing it" t
  traceIt (show n)