rzk-0.1.0: src/Free/Scoped/TH.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
module Free.Scoped.TH where
import Control.Monad (replicateM)
import Language.Haskell.TH
import Free.Scoped
mkConP :: Name -> [Pat] -> Pat
#if __GLASGOW_HASKELL__ >= 902
mkConP name pats = ConP name [] pats
#else
mkConP name pats = ConP name pats
#endif
makePatternsAll :: Name -> Q [Dec]
makePatternsAll ty = do
TyConI tyCon <- reify ty
case tyCon of
DataD _ _ _ _ cs _ -> concat <$> do
xs <- mapM makePatternFor cs
xs' <- makeCompletePragma cs
ys <- mapM makePatternEFor cs
ys' <- makeCompletePragmaE cs
zs <- mapM makePatternTFor cs
zs' <- makeCompletePragmaT cs
ws <- mapM makePatternTEFor cs
ws' <- makeCompletePragmaTE cs
return (xs ++ [xs'] ++ ys ++ [ys'] ++ zs ++ [zs'] ++ ws ++ [ws'])
_ -> fail "Can only make patterns for data types."
makeCompletePragma :: [Con] -> Q [Dec]
makeCompletePragma cs = do
DataConI varName _ _ <- reify 'Pure
let names = [mkName (removeF (nameBase name)) | NormalC name _ <- cs]
return [PragmaD (CompleteP (varName : names) Nothing)]
where
removeF s = take (length s - 1) s
makeCompletePragmaE :: [Con] -> Q [Dec]
makeCompletePragmaE cs = do
DataConI varName _ _ <- reify 'Pure
PatSynI extName _ <- reify 'ExtE
let names = [mkName (removeF (nameBase name)) | NormalC name _ <- cs]
return [PragmaD (CompleteP (varName : extName : names) Nothing)]
where
removeF s = take (length s - 1) s <> "E"
makeCompletePragmaT :: [Con] -> Q [Dec]
makeCompletePragmaT cs = do
DataConI varName _ _ <- reify 'Pure
let names = [mkName (removeF (nameBase name)) | NormalC name _ <- cs]
return [PragmaD (CompleteP (varName : names) Nothing)]
where
removeF s = take (length s - 1) s <> "T"
makeCompletePragmaTE :: [Con] -> Q [Dec]
makeCompletePragmaTE cs = do
DataConI varName _ _ <- reify 'Pure
let names = [mkName (removeF (nameBase name)) | NormalC name _ <- cs]
return [PragmaD (CompleteP (varName : names) Nothing)]
where
removeF s = take (length s - 1) s <> "TE"
makePatternFor :: Con -> Q [Dec]
makePatternFor = \case
NormalC name xs -> do
args <- replicateM (length xs) (newName "x")
let patName = mkName (removeF (nameBase name))
patArgs = PrefixPatSyn args
dir = ImplBidir
pat <- [p| Free $(pure (mkConP name (VarP <$> args))) |]
return [PatSynD patName patArgs dir pat]
_ -> fail "Can only make patterns for NormalC constructors"
where
removeF s = take (length s - 1) s
makePatternEFor :: Con -> Q [Dec]
makePatternEFor = \case
NormalC name xs -> do
args <- replicateM (length xs) (newName "x")
let patName = mkName (removeF (nameBase name))
patArgs = PrefixPatSyn args
dir = ImplBidir
pat <- [p| Free (InL $(pure (mkConP name (VarP <$> args)))) |]
return [PatSynD patName patArgs dir pat]
_ -> fail "Can only make patterns for NormalC constructors"
where
removeF s = take (length s - 1) s <> "E"
makePatternTFor :: Con -> Q [Dec]
makePatternTFor = \case
NormalC name xs -> do
t <- newName "type_"
args <- replicateM (length xs) (newName "x")
let patName = mkName (removeF (nameBase name))
patArgs = PrefixPatSyn (t : args)
dir = ImplBidir
pat <- [p| Free (AnnF $(pure (VarP t)) $(pure (mkConP name (VarP <$> args)))) |]
return [PatSynD patName patArgs dir pat]
_ -> fail "Can only make patterns for NormalC constructors"
where
removeF s = take (length s - 1) s <> "T"
makePatternTEFor :: Con -> Q [Dec]
makePatternTEFor = \case
NormalC name xs -> do
t <- newName "type_"
args <- replicateM (length xs) (newName "x")
let patName = mkName (removeF (nameBase name))
patArgs = PrefixPatSyn (t : args)
dir = ImplBidir
pat <- [p| Free (InL (AnnF $(pure (VarP t)) $(pure (mkConP name (VarP <$> args))))) |]
return [PatSynD patName patArgs dir pat]
_ -> fail "Can only make patterns for NormalC constructors"
where
removeF s = take (length s - 1) s <> "TE"