singletons-0.9.2: Data/Singletons/TH.hs
{-# LANGUAGE ExplicitNamespaces, CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Singletons.TH
-- Copyright : (C) 2013 Richard Eisenberg
-- License : BSD-style (see LICENSE)
-- Maintainer : Richard Eisenberg (eir@cis.upenn.edu)
-- Stability : experimental
-- Portability : non-portable
--
-- This module contains everything you need to derive your own singletons via
-- Template Haskell.
--
-- TURN ON @-XScopedTypeVariables@ IN YOUR MODULE IF YOU WANT THIS TO WORK.
--
----------------------------------------------------------------------------
module Data.Singletons.TH (
-- * Primary Template Haskell generation functions
singletons, singletonsOnly, genSingletons,
promote, promoteOnly,
-- ** Functions to generate equality instances
promoteEqInstances, promoteEqInstance,
singEqInstances, singEqInstance,
singEqInstancesOnly, singEqInstanceOnly,
singDecideInstances, singDecideInstance,
-- ** Utility function
cases,
-- * Basic singleton definitions
Sing(SFalse, STrue), SingI(..), SingKind(..), KindOf, Demote,
-- * Auxiliary definitions
-- | These definitions might be mentioned in code generated by Template Haskell,
-- so they must be in scope.
(:==), If, sIf, (:&&), SEq(..),
Any,
SDecide(..), (:~:)(..), Void, Refuted, Decision(..),
KProxy(..), SomeSing(..)
) where
import Data.Singletons.Singletons
import Data.Singletons.Promote
import Data.Singletons.Core
import Data.Singletons.Bool
import Data.Singletons.Eq
import Data.Singletons.Types
import Data.Singletons.Void
import GHC.Exts
import Language.Haskell.TH
import Language.Haskell.TH.Syntax ( Quasi(..) )
import Language.Haskell.TH.Desugar
import Data.Singletons.Util
import Control.Applicative
#if __GLASGOW_HASKELL__ >= 707
import Data.Type.Equality
import Data.Proxy
#endif
-- | The function 'cases' generates a case expression where each right-hand side
-- is identical. This may be useful if the type-checker requires knowledge of which
-- constructor is used to satisfy equality or type-class constraints, but where
-- each constructor is treated the same.
cases :: Quasi q
=> Name -- ^ The head of the type of the scrutinee. (Like @''Maybe@ or @''Bool@.)
-> q Exp -- ^ The scrutinee, in a Template Haskell quote
-> q Exp -- ^ The body, in a Template Haskell quote
-> q Exp
cases tyName expq bodyq = do
info <- reifyWithWarning tyName
case info of
TyConI (DataD _ _ _ ctors _) -> buildCases ctors
TyConI (NewtypeD _ _ _ ctor _) -> buildCases [ctor]
_ -> fail $ "Using <<cases>> with something other than a type constructor: "
++ (show tyName)
where buildCases ctors =
CaseE <$> expq <*>
mapM (\con -> Match (conToPat con) <$>
(NormalB <$> bodyq) <*> pure []) ctors
conToPat :: Con -> Pat
conToPat = ctor1Case
(\name tys -> ConP name (map (const WildP) tys))