packages feed

free-functors-1.2: src/Data/Functor/Cofree/Internal.hs

{-# LANGUAGE
    GADTs
  , PolyKinds
  , RankNTypes
  , ViewPatterns
  , TypeOperators
  , DeriveFunctor
  , DeriveFoldable
  , ConstraintKinds
  , TemplateHaskell
  , DeriveTraversable
  , FlexibleInstances
  , ScopedTypeVariables
  , UndecidableInstances
  , QuantifiedConstraints
  , MultiParamTypeClasses
  , UndecidableSuperClasses
  , StandaloneKindSignatures
  #-}
module Data.Functor.Cofree.Internal where

import Data.Monoid (Ap(..))

import Language.Haskell.TH.Syntax
import Data.DeriveLiftedInstances
import Data.Kind (Constraint)


kExp :: Q Exp
kExp = pure . VarE $ mkName "k"

kPat :: Pat
kPat = VarP $ mkName "k"

cofreeDeriv :: Name -> Derivator
cofreeDeriv cofree = idDeriv {
  cst = \e -> [| const $e $kExp |], -- Suppress "Defined but not used: ‘k’" warning
  res = \e -> [| $(pure (ConE cofree)) $kExp $e |],
  eff = \e -> [| $(pure (ConE cofree)) $kExp <$> $e |],
  inp = fmap (\vp -> ConP cofree [kPat, vp])
}

deriveCofreeInstance' :: Name -> Name -> Name -> Q [Dec]
deriveCofreeInstance' (pure . ConT -> cofree) ccofree (pure . ConT -> clss)
  = deriveInstance (cofreeDeriv ccofree)
      [t| forall a c. (c ~=> $clss, c ($cofree c a)) => $clss ($cofree c a) |]

type (~=>) :: (k -> Constraint) -> (k -> Constraint) -> Constraint
type a ~=> b = forall x. a x => b x