module Data.Singletons.Deriving.Bounded where
import Language.Haskell.TH.Ppr
import Language.Haskell.TH.Desugar
import Data.Singletons.Names
import Data.Singletons.Util
import Data.Singletons.Syntax
import Data.Singletons.Deriving.Infer
import Data.Singletons.Deriving.Util
import Control.Monad
mkBoundedInstance :: DsMonad q => DerivDesc q
mkBoundedInstance mb_ctxt ty (DataDecl _ _ cons) = do
when (null cons
|| (any (\(DCon _ _ _ f _) -> not . null . tysOfConFields $ f) cons
&& (not . null . tail $ cons))) $
fail ("Can't derive Bounded instance for "
++ pprint (typeToTH ty) ++ ".")
let (DCon _ _ minName fields _) = head cons
(DCon _ _ maxName _ _) = last cons
fieldsCount = length $ tysOfConFields fields
(minRHS, maxRHS) = case fieldsCount of
0 -> (DConE minName, DConE maxName)
_ ->
let minEqnRHS = foldExp (DConE minName)
(replicate fieldsCount (DVarE minBoundName))
maxEqnRHS = foldExp (DConE maxName)
(replicate fieldsCount (DVarE maxBoundName))
in (minEqnRHS, maxEqnRHS)
mk_rhs rhs = UFunction [DClause [] rhs]
constraints <- inferConstraintsDef mb_ctxt (DConPr boundedName) ty cons
return $ InstDecl { id_cxt = constraints
, id_name = boundedName
, id_arg_tys = [ty]
, id_sigs = mempty
, id_meths = [ (minBoundName, mk_rhs minRHS)
, (maxBoundName, mk_rhs maxRHS) ] }