module Text.Papillon.List (
listDec,
optionalDec
) where
import Language.Haskell.TH
import Control.Applicative
import Control.Monad
monadPlusN, mplusN, applicativeN, applyN, applyContN :: Bool -> Name
monadPlusN True = ''MonadPlus
monadPlusN False = mkName "MonadPlus"
applicativeN True = ''Applicative
applicativeN False = mkName "Applicative"
mplusN True = 'mplus
mplusN False = mkName "mplus"
applyN True = '(<$>)
applyN False = mkName "<$>"
applyContN True = '(<*>)
applyContN False = mkName "<*>"
m, a, p :: Name
m = mkName "m"
a = mkName "a"
p = mkName "p"
listDec :: Name -> Name -> Bool -> DecsQ
listDec list list1 th = sequence [
sigD list $ forallT [PlainTV m, PlainTV a]
(cxt [classP (monadPlusN th) [vm], classP (applicativeN th) [vm]]) $
arrowT `appT` (varT m `appT` varT a)
`appT` (varT m `appT` (listT `appT` varT a)),
sigD list1 $ forallT [PlainTV m, PlainTV a]
(cxt [classP (monadPlusN th) [vm], classP (applicativeN th) [vm]]) $
arrowT `appT` (varT m `appT` varT a)
`appT` (varT m `appT` (listT `appT` varT a)),
funD list $ (: []) $ flip (clause [varP p]) [] $ normalB $
infixApp (varE list1 `appE` varE p) (varE $ mplusN th) returnEmpty,
funD list1 $ (: []) $ flip (clause [varP p]) [] $ normalB $
infixApp (infixApp cons app (varE p)) next (varE list `appE` varE p)
] where
vm = varT m
returnEmpty = varE (mkName "return") `appE` listE []
cons = conE $ mkName ":"
app = varE $ applyN th
next = varE $ applyContN th
optionalDec :: Name -> Bool -> DecsQ
optionalDec optionalN th = sequence [
sigD optionalN $ mplusAndApp $ (varT m `appT` varT a) `arrT`
(varT m `appT` (conT (mkName "Maybe") `appT` varT a)),
funD optionalN $ (: []) $ flip (clause [varP p]) [] $ normalB $
conE (mkName "Just") `app` varE p `mplusE` returnNothing
] where
mplusAndApp = forallT [PlainTV m, PlainTV a] $ cxt [
classP (monadPlusN th) [varT m],
classP (applicativeN th) [varT m]
]
arrT f x = arrowT `appT` f `appT` x
mplusE x = infixApp x (varE $ mplusN th)
returnNothing = varE (mkName "return") `appE` conE (mkName "Nothing")
app x = infixApp x (varE $ applyN th)