thorn-0.1.0.3: Data/Thorn/Fold.hs
{-# LANGUAGE TemplateHaskell #-}
-- |
-- The module Data.Thorn.Fold.
module Data.Thorn.Fold (
unfixdata, unfixdataEx
, autoin, autoout, autohylo, autofold, autounfold
, unfixdataMutual, unfixdataMutualEx
, autoinMutual, autooutMutual, autohyloMutual, autofoldMutual, autounfoldMutual
) where
import Data.Thorn.Type
import Data.Thorn.Functor
import Language.Haskell.TH
import Control.Applicative
-- |
-- @unfixdata t@ provides a declaration of a data whose fixpoint is the recursive type @t@.
unfixdata :: TypeQ -> DecsQ
unfixdata = unfixdataEx ("Uf","") ("Uf","") ("&","") ("&","")
-- |
-- Special version of @unfixdata@. Note that
--
-- > unfixdata = unfixdataEx ("Uf","") ("Uf","") ("&","") ("&","")
unfixdataEx ::
(String,String) -- ^ prefix and suffix of type constructor
-> (String,String) -- ^ prefix and suffix of data constructor
-> (String,String) -- ^ prefix and suffix of infix type constructor
-> (String,String) -- ^ prefix and suffix of infix data constructor
-> TypeQ -- ^ data type
-> DecsQ -- ^ declaration of data
unfixdataEx (pretype,suftype) (predata,sufdata) (pretypeinfix,suftypeinfix) (predatainfix,sufdatainfix) t = do
(n, DataTx nm _ cxs) <- applyFixed 0 =<< type2typex [] [] =<< t
let modifytx (DataTx nm' vmp cxs') = if nm == nm' then VarTx $ mkName ("self") else DataTx nm' (map (\(nm'',tx) -> (nm'',modifytx tx)) vmp) (map modifycx cxs')
modifytx tx@(SeenDataTx nm' _) = if nm == nm' then VarTx $ mkName ("self") else modifytx tx
modifytx (TupleTx txs) = TupleTx (map modifytx txs)
modifytx (ArrowTx txa txb) = ArrowTx (modifytx txa) (modifytx txb)
modifytx (ListTx tx) = ListTx (modifytx tx)
modifytx tx = tx
modifycx (nm',txs) = (nm',map modifytx txs)
go (nm',txs) = do
ts <- map ((,) NotStrict) <$> mapM (typex2type . modifytx) txs
return $ NormalC (datanm nm') ts
cns <- mapM go cxs
return [DataD [] (typenm nm) (map var [0..n-1] ++ [self]) cns []]
where typenm nm
| elem (head s) ['A'..'Z'] = mkName $ pretype ++ s ++ suftype
| head s == '(' = mkName $ ":" ++ pretypeinfix ++ init (drop 2 s) ++ suftypeinfix
| otherwise = mkName $ ":" ++ pretypeinfix ++ tail s ++ suftypeinfix
where s = nameBase nm
datanm nm
| elem (head s) ['A'..'Z'] = mkName $ predata ++ s ++ sufdata
| head s == '(' = mkName $ ":" ++ predatainfix ++ init (drop 2 s) ++ sufdatainfix
| otherwise = mkName $ ":" ++ predatainfix ++ tail s ++ sufdatainfix
where s = nameBase nm
var i = PlainTV $ mkName ("t" ++ show i)
self = PlainTV $ mkName ("self")
autoin ::
TypeQ -- ^ @u@, un-recursive datatype
-> TypeQ -- ^ @t@, fixpoint of @u@
-> ExpQ -- ^ function with a type @u a0 .. an t -> t a0 .. an@
autoin u t = do
(_,DataTx _ _ cxsu) <- applyFixed 0 =<< type2typex [] [] =<< u
(_,DataTx _ _ cxst) <- applyFixed 0 =<< type2typex [] [] =<< t
u1 <- unique
u2 <- unique
let go ((nmu,txsu),(nmt,_)) = Match (ConP nmu (map newVarP [u2..u2+length txsu-1])) (NormalB (applistE (ConE nmt) (map newVarE [u2..u2+length txsu-1]))) []
return $ LamE [newVarP u1] (CaseE (newVarE u1) (map go (zip cxsu cxst)))
autoout ::
TypeQ -- ^ @u@, un-recursive datatype
-> TypeQ -- ^ @t@, fixpoint of @u@
-> ExpQ -- ^ function with a type @t x0 .. xn -> u x0 .. xn t@
autoout u t = do
(_,DataTx _ _ cxsu) <- applyFixed 0 =<< type2typex [] [] =<< u
(_,DataTx _ _ cxst) <- applyFixed 0 =<< type2typex [] [] =<< t
u1 <- unique
u2 <- unique
let go ((nmu,txsu),(nmt,_)) = Match (ConP nmt (map newVarP [u2..u2+length txsu-1])) (NormalB (applistE (ConE nmu) (map newVarE [u2..u2+length txsu-1]))) []
return $ LamE [newVarP u1] (CaseE (newVarE u1) (map go (zip cxsu cxst)))
autohylo ::
TypeQ -- ^ @u@, un-recursive datatype
-> ExpQ -- ^ function with a type @(a -> u x0 .. xn a) -> (u x0 .. xn b -> b) -> (a -> b)@
autohylo u = do
(n,DataTx nm _ cxs) <- applyFixed 0 =<< type2typex [] [] =<< u
f <- autofmap u
u <- unique
return $ LamE [newVarP u, newVarP (u+1)] (LetE [ValD (newVarP (u+3))
(NormalB (LamE [newVarP (u+2)] (AppE (newVarE (u+1)) (applistE f (replicate (n-1) (mkNameE "Prelude.id") ++ [newVarE (u+3)] ++ [AppE (newVarE u) (newVarE (u+2))])))))
[]] (newVarE (u+3)))
-- |
-- @autofold u t@ provides a folding function for a recursive type @t@.
autofold ::
TypeQ -- ^ @u@, un-recursive datatype
-> TypeQ -- ^ @t@, fixpoint of @u@
-> ExpQ -- ^ function with a type @(u x0 .. xn a -> a) -> (t -> a)@
autofold u t = do
o <- autoout u t
h <- autohylo u
return $ AppE h o
-- |
-- @autounfold t@ provides an unfolding function for the recursive type @t@.
autounfold ::
TypeQ -- ^ @u@, un-recursive datatype
-> TypeQ -- ^ @t@, fixpoint of @u@
-> ExpQ -- ^ function with a type @(a -> u x0 .. xn a) -> (a -> t)@
autounfold u t = do
i <- autoin u t
h <- autohylo u
u1 <- unique
return $ LamE [newVarP u1] (AppE (AppE h (newVarE u1)) i)
-- |
-- @unfixdataMutual ts@ is a mutual recursion version of @unfixdata t@.
unfixdataMutual :: [TypeQ] -> DecsQ
unfixdataMutual = unfixdataMutualEx ("Uf","") ("Uf","") ("&","") ("&","")
unfixdataMutualEx ::
(String,String) -- ^ prefix and suffix of type constructor
-> (String,String) -- ^ prefix and suffix of data constructor
-> (String,String) -- ^ prefix and suffix of infix type constructor
-> (String,String) -- ^ prefix and suffix of infix data constructor
-> [TypeQ] -- ^ data types
-> DecsQ -- ^ declarations of data
unfixdataMutualEx = undefined
autoinMutual :: [TypeQ] -> DecsQ
autoinMutual ts = fail "oh"
autooutMutual :: [TypeQ] -> DecsQ
autooutMutual ts = fail "oh"
autohyloMutual :: [TypeQ] -> DecsQ
autohyloMutual ts = fail "oh"
-- |
-- @autofoldMutual ts@ provides a folding function for the mutually recursive types @ts@.
autofoldMutual :: [TypeQ] -> ExpQ
autofoldMutual ts = do fail "oh"
-- |
-- @autounfoldMutual ts@ provides an unfolding function for the mutually recursive types @ts@.
autounfoldMutual :: [TypeQ] -> ExpQ
autounfoldMutual ts = do fail "oh"