{-# Language CPP, DeriveDataTypeable #-}
#if MIN_VERSION_base(4,4,0)
#define HAS_GENERICS
{-# Language DeriveGeneric #-}
#endif
module Language.Haskell.TH.Datatype.TyVarBndr (
TyVarBndr_
, TyVarBndrUnit
, TyVarBndrSpec
, Specificity(..)
, plainTVFlag
, kindedTVFlag
, plainTV
, kindedTV
, plainTVInferred
, plainTVSpecified
, kindedTVInferred
, kindedTVSpecified
, inferredSpec
, specifiedSpec
, elimTV
, mapTV
, mapTVName
, mapTVFlag
, mapTVKind
, traverseTV
, traverseTVName
, traverseTVFlag
, traverseTVKind
, mapMTV
, mapMTVName
, mapMTVFlag
, mapMTVKind
, changeTVFlags
, tvName
, tvKind
) where
import Control.Applicative
import Control.Monad
import Data.Data (Typeable, Data)
import Language.Haskell.TH.Lib
import Language.Haskell.TH.Syntax
#ifdef HAS_GENERICS
import GHC.Generics (Generic)
#endif
#if MIN_VERSION_template_haskell(2,17,0)
type TyVarBndr_ flag = TyVarBndr flag
#else
type TyVarBndr_ flag = TyVarBndr
type TyVarBndrUnit = TyVarBndr
type TyVarBndrSpec = TyVarBndr
data Specificity
= SpecifiedSpec
| InferredSpec
deriving (Show, Eq, Ord, Typeable, Data
#ifdef HAS_GENERICS
,Generic
#endif
)
inferredSpec :: Specificity
inferredSpec = InferredSpec
specifiedSpec :: Specificity
specifiedSpec = SpecifiedSpec
#endif
plainTVFlag :: Name -> flag -> TyVarBndr_ flag
#if MIN_VERSION_template_haskell(2,17,0)
plainTVFlag = PlainTV
#else
plainTVFlag n _ = PlainTV n
#endif
plainTVInferred :: Name -> TyVarBndrSpec
plainTVInferred n = plainTVFlag n InferredSpec
plainTVSpecified :: Name -> TyVarBndrSpec
plainTVSpecified n = plainTVFlag n SpecifiedSpec
kindedTVFlag :: Name -> flag -> Kind -> TyVarBndr_ flag
#if MIN_VERSION_template_haskell(2,17,0)
kindedTVFlag = KindedTV
#else
kindedTVFlag n _ kind = KindedTV n kind
#endif
kindedTVInferred :: Name -> Kind -> TyVarBndrSpec
kindedTVInferred n k = kindedTVFlag n InferredSpec k
kindedTVSpecified :: Name -> Kind -> TyVarBndrSpec
kindedTVSpecified n k = kindedTVFlag n SpecifiedSpec k
elimTV :: (Name -> r) -> (Name -> Kind -> r) -> TyVarBndr_ flag -> r
#if MIN_VERSION_template_haskell(2,17,0)
elimTV ptv _ktv (PlainTV n _) = ptv n
elimTV _ptv ktv (KindedTV n _ k) = ktv n k
#else
elimTV ptv _ktv (PlainTV n) = ptv n
elimTV _ptv ktv (KindedTV n k) = ktv n k
#endif
mapTV :: (Name -> Name) -> (flag -> flag') -> (Kind -> Kind)
-> TyVarBndr_ flag -> TyVarBndr_ flag'
#if MIN_VERSION_template_haskell(2,17,0)
mapTV fn fflag _fkind (PlainTV n flag) = PlainTV (fn n) (fflag flag)
mapTV fn fflag fkind (KindedTV n flag kind) = KindedTV (fn n) (fflag flag) (fkind kind)
#else
mapTV fn _fflag _fkind (PlainTV n) = PlainTV (fn n)
mapTV fn _fflag fkind (KindedTV n kind) = KindedTV (fn n) (fkind kind)
#endif
mapTVName :: (Name -> Name) -> TyVarBndr_ flag -> TyVarBndr_ flag
mapTVName fname = mapTV fname id id
mapTVFlag :: (flag -> flag') -> TyVarBndr_ flag -> TyVarBndr_ flag'
#if MIN_VERSION_template_haskell(2,17,0)
mapTVFlag = fmap
#else
mapTVFlag _ = id
#endif
mapTVKind :: (Kind -> Kind) -> TyVarBndr_ flag -> TyVarBndr_ flag
mapTVKind fkind = mapTV id id fkind
traverseTV :: Applicative f
=> (Name -> f Name) -> (flag -> f flag') -> (Kind -> f Kind)
-> TyVarBndr_ flag -> f (TyVarBndr_ flag')
#if MIN_VERSION_template_haskell(2,17,0)
traverseTV fn fflag _fkind (PlainTV n flag) =
liftA2 PlainTV (fn n) (fflag flag)
traverseTV fn fflag fkind (KindedTV n flag kind) =
liftA3 KindedTV (fn n) (fflag flag) (fkind kind)
#else
traverseTV fn _fflag _fkind (PlainTV n) =
PlainTV <$> fn n
traverseTV fn _fflag fkind (KindedTV n kind) =
liftA2 KindedTV (fn n) (fkind kind)
#endif
traverseTVName :: Functor f
=> (Name -> f Name)
-> TyVarBndr_ flag -> f (TyVarBndr_ flag)
#if MIN_VERSION_template_haskell(2,17,0)
traverseTVName fn (PlainTV n flag) =
(\n' -> PlainTV n' flag) <$> fn n
traverseTVName fn (KindedTV n flag kind) =
(\n' -> KindedTV n' flag kind) <$> fn n
#else
traverseTVName fn (PlainTV n) =
PlainTV <$> fn n
traverseTVName fn (KindedTV n kind) =
(\n' -> KindedTV n' kind) <$> fn n
#endif
traverseTVFlag :: Applicative f
=> (flag -> f flag')
-> TyVarBndr_ flag -> f (TyVarBndr_ flag')
#if MIN_VERSION_template_haskell(2,17,0)
traverseTVFlag fflag (PlainTV n flag) =
PlainTV n <$> fflag flag
traverseTVFlag fflag (KindedTV n flag kind) =
(\flag' -> KindedTV n flag' kind) <$> fflag flag
#else
traverseTVFlag _ = pure
#endif
traverseTVKind :: Applicative f
=> (Kind -> f Kind)
-> TyVarBndr_ flag -> f (TyVarBndr_ flag)
#if MIN_VERSION_template_haskell(2,17,0)
traverseTVKind _fkind tvb@PlainTV{} =
pure tvb
traverseTVKind fkind (KindedTV n flag kind) =
KindedTV n flag <$> fkind kind
#else
traverseTVKind _fkind tvb@PlainTV{} =
pure tvb
traverseTVKind fkind (KindedTV n kind) =
KindedTV n <$> fkind kind
#endif
mapMTV :: Monad m
=> (Name -> m Name) -> (flag -> m flag') -> (Kind -> m Kind)
-> TyVarBndr_ flag -> m (TyVarBndr_ flag')
#if MIN_VERSION_template_haskell(2,17,0)
mapMTV fn fflag _fkind (PlainTV n flag) =
liftM2 PlainTV (fn n) (fflag flag)
mapMTV fn fflag fkind (KindedTV n flag kind) =
liftM3 KindedTV (fn n) (fflag flag) (fkind kind)
#else
mapMTV fn _fflag _fkind (PlainTV n) =
liftM PlainTV (fn n)
mapMTV fn _fflag fkind (KindedTV n kind) =
liftM2 KindedTV (fn n) (fkind kind)
#endif
mapMTVName :: Monad m
=> (Name -> m Name)
-> TyVarBndr_ flag -> m (TyVarBndr_ flag)
#if MIN_VERSION_template_haskell(2,17,0)
mapMTVName fn (PlainTV n flag) =
liftM (\n' -> PlainTV n' flag) (fn n)
mapMTVName fn (KindedTV n flag kind) =
liftM (\n' -> KindedTV n' flag kind) (fn n)
#else
mapMTVName fn (PlainTV n) =
liftM PlainTV (fn n)
mapMTVName fn (KindedTV n kind) =
liftM (\n' -> KindedTV n' kind) (fn n)
#endif
mapMTVFlag :: Monad m
=> (flag -> m flag')
-> TyVarBndr_ flag -> m (TyVarBndr_ flag')
#if MIN_VERSION_template_haskell(2,17,0)
mapMTVFlag fflag (PlainTV n flag) =
liftM (PlainTV n) (fflag flag)
mapMTVFlag fflag (KindedTV n flag kind) =
liftM (\flag' -> KindedTV n flag' kind) (fflag flag)
#else
mapMTVFlag _ = return
#endif
mapMTVKind :: Monad m
=> (Kind -> m Kind)
-> TyVarBndr_ flag -> m (TyVarBndr_ flag)
#if MIN_VERSION_template_haskell(2,17,0)
mapMTVKind _fkind tvb@PlainTV{} =
return tvb
mapMTVKind fkind (KindedTV n flag kind) =
liftM (KindedTV n flag) (fkind kind)
#else
mapMTVKind _fkind tvb@PlainTV{} =
return tvb
mapMTVKind fkind (KindedTV n kind) =
liftM (KindedTV n) (fkind kind)
#endif
changeTVFlags :: newFlag -> [TyVarBndr_ oldFlag] -> [TyVarBndr_ newFlag]
#if MIN_VERSION_template_haskell(2,17,0)
changeTVFlags newFlag = map (newFlag <$)
#else
changeTVFlags _ = id
#endif
tvName :: TyVarBndr_ flag -> Name
tvName = elimTV id (\n _ -> n)
tvKind :: TyVarBndr_ flag -> Kind
tvKind = elimTV (\_ -> starK) (\_ k -> k)