th-lego-0.3: library/THLego/Helpers.hs
module THLego.Helpers where
import qualified Data.Text as Text
import Language.Haskell.TH.Syntax
import THLego.Prelude
import qualified TemplateHaskell.Compat.V0208 as Compat
-- * Decs
typeSynonymDec :: Name -> Type -> Dec
typeSynonymDec a b =
TySynD a [] b
recordNewtypeDec :: Name -> Name -> Type -> Dec
recordNewtypeDec _name _accessorName _type =
NewtypeD [] _name [] Nothing _con []
where
_con =
RecC _name [(_accessorName, noBang, _type)]
normalNewtypeDec :: Name -> Type -> Dec
normalNewtypeDec _name _type =
NewtypeD [] _name [] Nothing _con []
where
_con =
NormalC _name [(noBang, _type)]
recordAdtDec :: Name -> [(Name, Type)] -> Dec
recordAdtDec typeName fields =
DataD [] typeName [] Nothing [con] []
where
con =
RecC typeName (fmap (\(fieldName, fieldType) -> (fieldName, fieldBang, fieldType)) fields)
productAdtDec :: Name -> [Type] -> Dec
productAdtDec typeName memberTypes =
DataD [] typeName [] Nothing [con] []
where
con =
NormalC typeName (fmap ((fieldBang,)) memberTypes)
sumAdtDec :: Name -> [(Name, [Type])] -> Dec
sumAdtDec a b =
DataD [] a [] Nothing (fmap (uncurry sumCon) b) []
sumCon :: Name -> [Type] -> Con
sumCon a b =
NormalC a (fmap (fieldBang,) b)
enumDec :: Name -> [Name] -> Dec
enumDec a b =
DataD [] a [] Nothing (fmap (\c -> NormalC c []) b) []
-- *
textName :: Text -> Name
textName =
mkName . Text.unpack
textTyLit :: Text -> TyLit
textTyLit =
StrTyLit . Text.unpack
noBang :: Bang
noBang =
Bang NoSourceUnpackedness NoSourceStrictness
fieldBang :: Bang
fieldBang =
Bang NoSourceUnpackedness SourceStrict
multiAppT :: Type -> [Type] -> Type
multiAppT base args =
foldl' AppT base args
multiAppE :: Exp -> [Exp] -> Exp
multiAppE base args =
foldl' AppE base args
arrowChainT :: [Type] -> Type -> Type
arrowChainT params result =
foldr (\a b -> AppT (AppT ArrowT a) b) result params
appliedTupleT :: [Type] -> Type
appliedTupleT a =
foldl' AppT (TupleT (length a)) a
appliedTupleOrSingletonT :: [Type] -> Type
appliedTupleOrSingletonT =
\case
[a] -> a
a -> appliedTupleT a
appliedTupleE :: [Exp] -> Exp
appliedTupleE =
Compat.tupE
appliedTupleOrSingletonE :: [Exp] -> Exp
appliedTupleOrSingletonE =
\case
[a] -> a
a -> appliedTupleE a
nameString :: Name -> String
nameString (Name (OccName x) _) =
x
decimalIndexName :: Int -> Name
decimalIndexName =
mkName . showChar '_' . show
alphabeticIndexName :: Int -> Name
alphabeticIndexName a =
mkName string
where
string =
showIntAtBase 26 (chr . (+) 97) a ""
enumAlphabeticNames :: Int -> [Name]
enumAlphabeticNames =
fmap alphabeticIndexName . enumFromTo 0 . pred
-- |
-- Map every element of a list with a new name.
{-# INLINE mapWithAlphabeticName #-}
mapWithAlphabeticName :: (Name -> a -> b) -> [a] -> [b]
mapWithAlphabeticName f list =
foldr step (const []) list 0
where
step a next !index =
f (alphabeticIndexName index) a : next (succ index)
aName :: Name
aName =
mkName "a"
bName :: Name
bName =
mkName "b"
cName :: Name
cName =
mkName "c"
eqConstraintT :: Name -> Type -> Type
eqConstraintT name =
AppT (AppT EqualityT (VarT name))
-- *
applicativeChainE :: Exp -> [Exp] -> Exp
applicativeChainE mappingE apEList =
case apEList of
h : t ->
intersperseInfixE
(VarE '(<*>))
(InfixE (Just mappingE) (VarE '(<$>)) (Just h) :| t)
_ ->
AppE (VarE 'pure) mappingE
intersperseInfixE :: Exp -> NonEmpty Exp -> Exp
intersperseInfixE op =
foldl1 (\l r -> InfixE (Just l) op (Just r))
textLitE :: Text -> Exp
textLitE =
LitE . StringL . Text.unpack