{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Control.Monad.Freer.TH
( makeEffect
, makeEffect_
)
where
import Control.Monad (forM, unless)
import Control.Monad.Freer (send, Member, Eff)
import Data.Char (toLower)
import Language.Haskell.TH
import Prelude
makeEffect :: Name -> Q [Dec]
makeEffect :: Name -> Q [Dec]
makeEffect = Bool -> Name -> Q [Dec]
genFreer Bool
True
makeEffect_ :: Name -> Q [Dec]
makeEffect_ :: Name -> Q [Dec]
makeEffect_ = Bool -> Name -> Q [Dec]
genFreer Bool
False
genFreer :: Bool -> Name -> Q [Dec]
genFreer :: Bool -> Name -> Q [Dec]
genFreer Bool
makeSigs Name
tcName = do
Extension -> Q Bool
isExtEnabled Extension
FlexibleContexts
Q Bool -> (Bool -> Q ()) -> Q ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Bool -> Q () -> Q ()) -> Q () -> Bool -> Q ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Q ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"makeEffect requires FlexibleContexts to be enabled")
Name -> Q Info
reify Name
tcName Q Info -> (Info -> Q [Dec]) -> Q [Dec]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
TyConI (DataD Cxt
_ Name
_ [TyVarBndr]
_ Maybe Kind
_ [Con]
cons [DerivClause]
_) -> do
[Dec]
sigs <- (Dec -> Bool) -> [Dec] -> [Dec]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Dec -> Bool
forall a b. a -> b -> a
const Bool
makeSigs) ([Dec] -> [Dec]) -> Q [Dec] -> Q [Dec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Con -> Q Dec) -> [Con] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Con -> Q Dec
genSig [Con]
cons
[Dec]
decs <- (Con -> Q Dec) -> [Con] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Con -> Q Dec
genDecl [Con]
cons
[Dec] -> Q [Dec]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Dec] -> Q [Dec]) -> [Dec] -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ [Dec]
sigs [Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
++ [Dec]
decs
Info
_ -> String -> Q [Dec]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"makeEffect expects a type constructor"
getDeclName :: Name -> Name
getDeclName :: Name -> Name
getDeclName = String -> Name
mkName (String -> Name) -> (Name -> String) -> Name -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> String -> String
forall a. (a -> a) -> [a] -> [a]
overFirst Char -> Char
toLower (String -> String) -> (Name -> String) -> Name -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> String
nameBase
where
overFirst :: (a -> a) -> [a] -> [a]
overFirst a -> a
f (a
a : [a]
as) = a -> a
f a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
as
overFirst a -> a
_ [a]
as = [a]
as
genDecl :: Con -> Q Dec
genDecl :: Con -> Q Dec
genDecl (ForallC [TyVarBndr]
_ Cxt
_ Con
con) = Con -> Q Dec
genDecl Con
con
genDecl (GadtC [Name
cName] [BangType]
tArgs Kind
_ ) = do
let fnName :: Name
fnName = Name -> Name
getDeclName Name
cName
let arity :: Int
arity = [BangType] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BangType]
tArgs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
[Name]
dTypeVars <- [Int] -> (Int -> Q Name) -> Q [Name]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Int
0 .. Int
arity] ((Int -> Q Name) -> Q [Name]) -> (Int -> Q Name) -> Q [Name]
forall a b. (a -> b) -> a -> b
$ Q Name -> Int -> Q Name
forall a b. a -> b -> a
const (Q Name -> Int -> Q Name) -> Q Name -> Int -> Q Name
forall a b. (a -> b) -> a -> b
$ String -> Q Name
newName String
"a"
Dec -> Q Dec
forall (m :: * -> *) a. Monad m => a -> m a
return (Dec -> Q Dec) -> Dec -> Q Dec
forall a b. (a -> b) -> a -> b
$ Name -> [Clause] -> Dec
FunD Name
fnName ([Clause] -> Dec) -> (Clause -> [Clause]) -> Clause -> Dec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Clause -> [Clause]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Clause -> Dec) -> Clause -> Dec
forall a b. (a -> b) -> a -> b
$ [Pat] -> Body -> [Dec] -> Clause
Clause
(Name -> Pat
VarP (Name -> Pat) -> [Name] -> [Pat]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Name]
dTypeVars)
(Exp -> Body
NormalB (Exp -> Body) -> (Exp -> Exp) -> Exp -> Body
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Exp -> Exp -> Exp
AppE (Name -> Exp
VarE 'send) (Exp -> Body) -> Exp -> Body
forall a b. (a -> b) -> a -> b
$ (Exp -> Name -> Exp) -> Exp -> [Name] -> Exp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl
(\Exp
b -> Exp -> Exp -> Exp
AppE Exp
b (Exp -> Exp) -> (Name -> Exp) -> Name -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Exp
VarE)
(Name -> Exp
ConE Name
cName)
[Name]
dTypeVars
)
[]
genDecl Con
_ = String -> Q Dec
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"genDecl expects a GADT constructor"
genType :: Con -> Q Type
genType :: Con -> Q Kind
genType (ForallC [TyVarBndr]
tyVarBindings Cxt
conCtx Con
con)
= [TyVarBndr] -> Cxt -> Kind -> Kind
ForallT [TyVarBndr]
tyVarBindings Cxt
conCtx (Kind -> Kind) -> Q Kind -> Q Kind
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Con -> Q Kind
genType Con
con
genType (GadtC [Name]
_ [BangType]
tArgs' (AppT Kind
eff Kind
tRet)) = do
Name
effs <- String -> Q Name
newName String
"effs"
let
tArgs :: Cxt
tArgs = (BangType -> Kind) -> [BangType] -> Cxt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap BangType -> Kind
forall a b. (a, b) -> b
snd [BangType]
tArgs'
memberConstraint :: Kind
memberConstraint = Name -> Kind
ConT ''Member Kind -> Kind -> Kind
`AppT` Kind
eff Kind -> Kind -> Kind
`AppT` Name -> Kind
VarT Name
effs
resultType :: Kind
resultType = Name -> Kind
ConT ''Eff Kind -> Kind -> Kind
`AppT` Name -> Kind
VarT Name
effs Kind -> Kind -> Kind
`AppT` Kind
tRet
Kind -> Q Kind
forall (m :: * -> *) a. Monad m => a -> m a
return
#if MIN_VERSION_template_haskell(2,17,0)
. ForallT [PlainTV effs SpecifiedSpec] [memberConstraint]
#else
(Kind -> Q Kind) -> (Cxt -> Kind) -> Cxt -> Q Kind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TyVarBndr] -> Cxt -> Kind -> Kind
ForallT [Name -> TyVarBndr
PlainTV Name
effs] [Kind
memberConstraint]
#endif
(Kind -> Kind) -> (Cxt -> Kind) -> Cxt -> Kind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cxt -> Kind
foldArrows
(Cxt -> Q Kind) -> Cxt -> Q Kind
forall a b. (a -> b) -> a -> b
$ Cxt
tArgs
Cxt -> Cxt -> Cxt
forall a. [a] -> [a] -> [a]
++ [Kind
resultType]
genType Con
_ = String -> Q Kind
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"genSig expects a GADT constructor"
simplifyBndrs :: Type -> Type
simplifyBndrs :: Kind -> Kind
simplifyBndrs (ForallT [TyVarBndr]
bndrs Cxt
tcxt Kind
t) = [TyVarBndr] -> Cxt -> Kind -> Kind
ForallT ((TyVarBndr -> TyVarBndr) -> [TyVarBndr] -> [TyVarBndr]
forall a b. (a -> b) -> [a] -> [b]
map TyVarBndr -> TyVarBndr
simplifyBndr [TyVarBndr]
bndrs) Cxt
tcxt (Kind -> Kind
simplifyBndrs Kind
t)
simplifyBndrs (AppT Kind
t1 Kind
t2) = Kind -> Kind -> Kind
AppT (Kind -> Kind
simplifyBndrs Kind
t1) (Kind -> Kind
simplifyBndrs Kind
t2)
simplifyBndrs (SigT Kind
t Kind
k) = Kind -> Kind -> Kind
SigT (Kind -> Kind
simplifyBndrs Kind
t) Kind
k
simplifyBndrs (InfixT Kind
t1 Name
n Kind
t2) = Kind -> Name -> Kind -> Kind
InfixT (Kind -> Kind
simplifyBndrs Kind
t1) Name
n (Kind -> Kind
simplifyBndrs Kind
t2)
simplifyBndrs (UInfixT Kind
t1 Name
n Kind
t2) = Kind -> Name -> Kind -> Kind
InfixT (Kind -> Kind
simplifyBndrs Kind
t1) Name
n (Kind -> Kind
simplifyBndrs Kind
t2)
simplifyBndrs (ParensT Kind
t) = Kind -> Kind
ParensT (Kind -> Kind
simplifyBndrs Kind
t)
simplifyBndrs Kind
t = Kind
t
#if MIN_VERSION_template_haskell(2,17,0)
simplifyBndr :: TyVarBndrSpec -> TyVarBndrSpec
simplifyBndr (KindedTV tv f StarT) = PlainTV tv f
#else
simplifyBndr :: TyVarBndr -> TyVarBndr
simplifyBndr :: TyVarBndr -> TyVarBndr
simplifyBndr (KindedTV Name
tv Kind
StarT) = Name -> TyVarBndr
PlainTV Name
tv
#endif
simplifyBndr TyVarBndr
bndr = TyVarBndr
bndr
genSig :: Con -> Q Dec
genSig :: Con -> Q Dec
genSig Con
con = do
let
getConName :: Con -> f Name
getConName (ForallC [TyVarBndr]
_ Cxt
_ Con
c) = Con -> f Name
getConName Con
c
getConName (GadtC [Name
n] [BangType]
_ Kind
_) = Name -> f Name
forall (f :: * -> *) a. Applicative f => a -> f a
pure Name
n
getConName Con
c = String -> f Name
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> f Name) -> String -> f Name
forall a b. (a -> b) -> a -> b
$ String
"failed to get GADT name from " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Con -> String
forall a. Show a => a -> String
show Con
c
Name
conName <- Con -> Q Name
forall (f :: * -> *). MonadFail f => Con -> f Name
getConName Con
con
Name -> Kind -> Dec
SigD (Name -> Name
getDeclName Name
conName) (Kind -> Dec) -> (Kind -> Kind) -> Kind -> Dec
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Kind -> Kind
simplifyBndrs (Kind -> Dec) -> Q Kind -> Q Dec
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Con -> Q Kind
genType Con
con
foldArrows :: [Type] -> Type
foldArrows :: Cxt -> Kind
foldArrows = (Kind -> Kind -> Kind) -> Cxt -> Kind
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (Kind -> Kind -> Kind
AppT (Kind -> Kind -> Kind) -> (Kind -> Kind) -> Kind -> Kind -> Kind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Kind -> Kind -> Kind
AppT Kind
ArrowT)