----------------------------------------------------------------------------- -- | -- Module : Data.Spine -- Copyright : (c) 2010 University of Minho -- License : BSD3 -- -- Maintainer : hpacheco@di.uminho.pt -- Stability : experimental -- Portability : non-portable -- -- Pointless Rewrite: -- automatic transformation system for point-free programs -- -- Representation of spines for generic programming a la SYB revolutions. -- ----------------------------------------------------------------------------- module Data.Spine where import Data.Type import Data.Monoid hiding (Any) import Generics.Pointless.Functors import Generics.Pointless.Combinators -- * A spine representation for data values à la SYB revolutions data Typed a = Type a :| a data Spine a where As :: a -> Con -> Spine a Ap :: Spine (a -> b) -> Typed a -> Spine b data Fixity = Prefix | Infix deriving Eq data Con = Con {name :: String, fixity :: Fixity} scon n = Con {name = show n, fixity = Prefix} pcon s = Con {name = s, fixity = Prefix} icon s = Con {name = s, fixity = Infix} -- | Converting from a spine to a value fromSpine :: Spine a -> a fromSpine (c `As` _) = c fromSpine (Ap f (_ :| a)) = (fromSpine f) a -- | Converting from a value to a spine toSpine :: Type a -> a -> Spine a toSpine Any x = x `As` (pcon "Any") toSpine (Id a) x = x `As` (pcon "Id") toSpine Int n = n `As` (scon n) toSpine Bool n = n `As` (scon n) toSpine Char n = n `As` (scon n) toSpine One x = x `As` (pcon "(_L::One)") toSpine (Either a _) (Left x) = Left `As` (pcon "Left") `Ap` (a :| x) toSpine (Either _ b) (Right y) = Right `As` (pcon "Right") `Ap` (b :| y) toSpine (Prod a b) (x,y) = (,) `As` (icon ",") `Ap` (a :| x) `Ap` (b :| y) toSpine (Fun a b) f = f `As` (pcon "Fun") toSpine (Lns c a) l = l `As` (pcon "Lns") toSpine (a@(Data s fctr)) v = inn `As` (pcon $ "innT" ++ s) `Ap` ((rep fctr a) :| out v) toSpine Dynamic (Dyn t x) = Dyn t `As` (pcon "Dyn") `Ap` (t :| x) toSpine TP x = x `As` (pcon "TP") toSpine (TU a) x = x `As` (pcon "TQ") toSpine (Pf _) HOLE = HOLE `As` (pcon "_L") toSpine (Pf _) TOP = TOP `As` (pcon "T") toSpine (Pf (Fun _ _)) (FUN s f) = (FUN s f) `As` (pcon s) toSpine (Pf (Fun a c)) (CONV e@(Left _) f) = CONV e `As` (pcon "lconv") `Ap` (Pf (Fun c a) :| f) toSpine (Pf (Fun a c)) (CONV e@(Right _) f) = CONV e `As` (pcon "rconv") `Ap` (Pf (Fun c a) :| f) toSpine (Pf (Lns a c)) (CONV_LNS e@(Left _) f) = CONV_LNS e `As` (pcon "lconv") `Ap` (Pf (Lns c a) :| f) toSpine (Pf (Lns a c)) (CONV_LNS e@(Right _) f) = CONV_LNS e `As` (pcon "rconv") `Ap` (Pf (Lns c a) :| f) toSpine (Pf (Lns c a)) (LNS s l) = (LNS s l) `As` (pcon s) toSpine (Pf (Fun c a)) (COMPF fctr b f g) = (COMPF fctr b) `As` (pcon $ "compf " ++ show fctr) `Ap` (Pf (Fun (rep fctr b) a) :| f) `Ap` (Pf (Fun c (rep fctr b)) :| g) toSpine (Pf (Lns c a)) (COMPF_LNS fctr b f g) = (COMPF_LNS fctr b) `As` (pcon $ "compf_lns " ++ show fctr) `Ap` (Pf (Lns (rep fctr b) a) :| f) `Ap` (Pf (Lns c (rep fctr b)) :| g) toSpine (Pf (Fun a b)) (PROTECT f) = PROTECT `As` (pcon "protect") `Ap` (Pf (Fun a b) :| f) toSpine (Pf (Lns a b)) (PROTECT_LNS f) = PROTECT_LNS `As` (pcon "protect_lns") `Ap` (Pf (Lns a b) :| f) toSpine (Pf _) (VAR s) = VAR s `As` (pcon s) toSpine (Pf (Fun a b)) (PNT vb) = PNT vb `As` (pcon $ showL ["pnt",gshow b vb]) toSpine (Pf (Fun _ _)) BANG = BANG `As` (pcon "bang") toSpine (Pf (Fun a c)) (COMP b f g) = COMP b `As` (icon ".") `Ap` (Pf (Fun b c) :| f) `Ap` (Pf (Fun a b) :| g) toSpine (Pf (Fun _ _)) FST = FST `As` (pcon "fst") toSpine (Pf (Fun _ _)) SND = SND `As` (pcon "snd") toSpine (Pf (Fun a (Prod b c))) (SPLIT f g) = SPLIT `As` (icon "/\\") `Ap` (Pf (Fun a b) :| f) `Ap` (Pf (Fun a c) :| g) toSpine (Pf (Fun (Prod a b) (Prod c d))) (PROD f g) = PROD `As` (icon "><") `Ap` (Pf (Fun a c) :| f) `Ap` (Pf (Fun b d) :| g) toSpine (Pf (Fun _ _)) INL = INL `As` (pcon "inl") toSpine (Pf (Fun _ _)) INR = INR `As` (pcon "inr") toSpine (Pf (Fun (Either a b) c)) (EITHER f g) = EITHER `As` (icon "\\/") `Ap` (Pf (Fun a c) :| f) `Ap` (Pf (Fun b c) :| g) toSpine (Pf (Fun (Either a b) (Either c d))) (SUM f g) = SUM `As` (icon "-|-") `Ap` (Pf (Fun a c) :| f) `Ap` (Pf (Fun b d) :| g) toSpine (Pf func) ZERO = aux func where aux :: Monoid y => Type (x -> y) -> Spine (Pf (x -> y)) aux t@(Fun _ (Data "List" fctr)) = ZERO `As` pcon "nil" aux (Fun _ Int) = ZERO `As` pcon "const 0" aux _ = ZERO `As` pcon "mempty" toSpine (Pf func) PLUS = aux func where aux :: Monoid a => Type ((a,a) -> a) -> Spine (Pf ((a,a) -> a)) aux (Fun _ (Data "List" fctr)) = PLUS `As` pcon "(++)" aux (Fun _ Int) = PLUS `As` pcon "(uncurry (+))" aux _ = PLUS `As` pcon "mappend" toSpine (Pf (Fun _ _)) ID = ID `As` (pcon "id") toSpine (Pf (Fun _ _)) SWAP = SWAP `As` (pcon "swap") toSpine (Pf (Fun _ _)) COSWAP = COSWAP `As` (pcon "coswap") toSpine (Pf (Fun _ _)) DISTL = DISTL `As` (pcon "distl") toSpine (Pf (Fun _ _)) UNDISTL = UNDISTL `As` (pcon "undistl") toSpine (Pf (Fun _ _)) DISTR = DISTR `As` (pcon "distr") toSpine (Pf (Fun _ _)) UNDISTR = UNDISTR `As` (pcon "undistr") toSpine (Pf (Fun _ _)) ASSOCL = ASSOCL `As` (pcon "assocl") toSpine (Pf (Fun _ _)) ASSOCR = ASSOCR `As` (pcon "assocr") toSpine (Pf (Fun _ _)) COASSOCL = COASSOCL `As` (pcon "coassocl") toSpine (Pf (Fun _ _)) COASSOCR = COASSOCR `As` (pcon "coassocr") toSpine (Pf (Fun _ a@(Data s _))) INN = INN `As` (pcon $ "inn" ++ s) toSpine (Pf (Fun a@(Data s _) _)) OUT = OUT `As` (pcon $ "out" ++ s) toSpine (Pf (Fun _ _)) (FMAP fctr (Fun a c) f) = FMAP fctr (Fun a c) `As` (pcon $ "fmap") `Ap` (Pf (Fun a c) :| f) toSpine (Pf (Fun _ _)) (FZIP fctr t f) = FZIP fctr t `As` (pcon $ "fzip") `Ap` (Pf t :| f) toSpine (Pf (Fun a b@(Data s fctr))) (ANA f) = ANA `As` (pcon $ "ana" ++ s) `Ap` (Pf (Fun a (rep fctr a)) :| f) toSpine (Pf (Fun a@(Data s fctr) b)) (CATA f) = CATA `As` (pcon $ "cata" ++ s) `Ap` (Pf (Fun (rep fctr b) b) :| f) toSpine (Pf func) (PARA f) = aux func f where aux :: Type (a -> c) -> Pf (F a (c,a) -> c) -> Spine (Pf (a -> c)) aux (Fun a@(Data _ fctr) c) f = (PARA `As` pcon ("para")) `Ap` (Pf (Fun (rep fctr (Prod c a)) c) :| f) toSpine (Pf (Fun c a)) (GET l) = GET `As` (pcon "get") `Ap` (Pf (Lns c a) :| l) toSpine (Pf (Fun (Prod a c) _)) (PUT l) = PUT `As` (pcon "put") `Ap` (Pf (Lns c a) :| l) toSpine (Pf (Fun a c)) (CREATE l) = CREATE `As` (pcon "create") `Ap` (Pf (Lns c a) :| l) toSpine (Pf (Lns c a)) (COMP_LNS b f g) = (COMP_LNS b) `As` (icon ".<") `Ap` (Pf (Lns b a) :| f) `Ap` (Pf (Lns c b) :| g) toSpine (Pf (Lns (Prod a b) _)) (FST_LNS f) = FST_LNS `As` (pcon "fst_lns") `Ap` (Pf (Fun a b) :| f) toSpine (Pf (Lns (Prod a b) _)) (SND_LNS f) = SND_LNS `As` (pcon "snd_lns") `Ap` (Pf (Fun b a) :| f) toSpine (Pf (Lns (Prod c d) (Prod a b))) (PROD_LNS f g) = PROD_LNS `As` (icon "><<") `Ap` (Pf (Lns c a) :| f) `Ap` (Pf (Lns d b) :| g) toSpine (Pf (Lns (Either a b) c)) (EITHER_LNS x f g) = EITHER_LNS `As` (icon "\\/<") `Ap` (Pf (Fun c (Either One One)) :| x) `Ap` (Pf (Lns a c) :| f) `Ap` (Pf (Lns b c) :| g) toSpine (Pf (Lns (Either c d) (Either a b))) (SUM_LNS f g) = SUM_LNS `As` (icon "-|-<") `Ap` (Pf (Lns c a) :| f) `Ap` (Pf (Lns d b) :| g) toSpine (Pf (Lns (Either c d) (Either a b))) (SUMW_LNS x y f g) = SUMW_LNS `As` (pcon "sum_lns") `Ap` (Pf (Fun (Prod a d) c) :| x) `Ap` (Pf (Fun (Prod b c) d) :| y) `Ap` (Pf (Lns c a) :| f) `Ap` (Pf (Lns d b) :| g) toSpine (Pf (Lns c One)) (BANG_LNS f) = BANG_LNS `As` (pcon "(!<)") `Ap` (Pf (Fun One c) :| f) toSpine (Pf (Lns c (Prod One _))) (BANGL_LNS) = BANGL_LNS `As` (pcon "bangl") toSpine (Pf (Lns c (Prod _ One))) (BANGR_LNS) = BANGR_LNS `As` (pcon "bangr") toSpine (Pf (Lns _ _)) ID_LNS = ID_LNS `As` (pcon "id_lns") toSpine (Pf (Lns _ _)) SWAP_LNS = SWAP_LNS `As` (pcon "swap_lns") toSpine (Pf (Lns _ _)) COSWAP_LNS = COSWAP_LNS `As` (pcon "coswap_lns") toSpine (Pf (Lns _ _)) DISTL_LNS = DISTL_LNS `As` (pcon "distl_lns") toSpine (Pf (Lns _ _)) UNDISTL_LNS = UNDISTL_LNS `As` (pcon "undistl_lns") toSpine (Pf (Lns _ _)) DISTR_LNS = DISTR_LNS `As` (pcon "distr_lns") toSpine (Pf (Lns _ _)) UNDISTR_LNS = UNDISTR_LNS `As` (pcon "undistr_lns") toSpine (Pf (Lns _ _)) ASSOCL_LNS = ASSOCL_LNS `As` (pcon "assocl_lns") toSpine (Pf (Lns _ _)) ASSOCR_LNS = ASSOCR_LNS `As` (pcon "assocr_lns") toSpine (Pf (Lns _ _)) COASSOCL_LNS = COASSOCL_LNS `As` (pcon "coassocl_lns") toSpine (Pf (Lns _ _)) COASSOCR_LNS = COASSOCR_LNS `As` (pcon "coassocr_lns") toSpine (Pf (Lns _ a@(Data s _))) INN_LNS = INN_LNS `As` (pcon $ "inn" ++ s ++ "_lns") toSpine (Pf (Lns a@(Data s _) _)) OUT_LNS = OUT_LNS `As` (pcon $ "out" ++ s ++ "_lns") toSpine (Pf (Lns _ _)) (FMAP_LNS fctr (Fun c a) (f)) = FMAP_LNS fctr (Fun c a) `As` (pcon $ "fmap_lns " ++ show fctr) `Ap` (Pf (Lns c a) :| f) toSpine (Pf (Lns a b@(Data s fctr))) (ANA_LNS f) = ANA_LNS `As` (pcon $ "ana" ++ s ++ "_lns") `Ap` (Pf (Lns a (rep fctr a)) :| f) toSpine (Pf (Lns a@(Data s fctr) b)) (CATA_LNS f) = CATA_LNS `As` (pcon $ "cata" ++ s ++ "_lns") `Ap` (Pf (Lns (rep fctr b) b) :| f) toSpine (Pf (Lns la lb)) (MAP_LNS f) = MAP_LNS `As` (pcon "map_lns") `Ap` (Pf (Lns (unlist la) (unlist lb)) :| f) toSpine (Pf (Lns la _)) (LENGTH_LNS v) = LENGTH_LNS v `As` (pcon $ showL["length_lns",gshow (unlist la) v]) toSpine (Pf (Lns _ _)) FILTER_LEFT_LNS = FILTER_LEFT_LNS `As` (pcon "filter_left_lns") toSpine (Pf (Lns _ _)) FILTER_RIGHT_LNS = FILTER_RIGHT_LNS `As` (pcon "filter_right_lns") toSpine (Pf (Lns _ _)) CAT_LNS = CAT_LNS `As` (pcon "cat_lns") toSpine (Pf (Lns _ _)) CONCAT_LNS = CONCAT_LNS `As` (pcon "concat_lns") toSpine (Pf (Lns _ _)) SUML_LNS = SUML_LNS `As` (pcon "suml_lns") toSpine (Pf (Lns _ _)) PLUS_LNS = PLUS_LNS `As` (pcon "plus_lns") toSpine (Pf _) (APPLY t f) = (APPLY t `As` pcon ("apT " ++ show t)) `Ap` (Pf TP :| f) toSpine (Pf _) (MKT t f) = (MKT t `As` pcon ("mkT " ++ show t)) `Ap` (Pf (Fun t t) :| f) toSpine (Pf _) NOP = NOP `As` pcon "nop" toSpine (Pf _) (SEQ f g) = (SEQ `As` pcon "seq") `Ap` (Pf TP :| f) `Ap` (Pf TP :| g) toSpine (Pf _) (EXTT f t g) = ((\x y -> EXTT x t y) `As` pcon "extT") `Ap` (Pf TP :| f) `Ap` (Pf (Fun t t) :| g) toSpine (Pf _) (ALL f) = (ALL `As` pcon "gmapT") `Ap` (Pf TP :| f) toSpine (Pf _) (EVERYWHERE f) = (EVERYWHERE `As` pcon "everywhere") `Ap` (Pf TP :| f) toSpine (Pf _) (EVERYWHERE' f) = (EVERYWHERE' `As` pcon "everywhere'") `Ap` (Pf TP :| f) toSpine (Pf func) (APPLYQ t f) = aux func t f where aux :: Type (a -> r) -> Type a -> Pf (Q r) -> Spine (Pf (a -> r)) aux (Fun _ r) t f = (APPLYQ t `As` pcon ("apQ " ++ show t)) `Ap` (Pf (TU r) :| f) toSpine (Pf func) (MKQ t f) = aux func t f where aux :: Monoid r => Type (Q r) -> Type a -> Pf (a -> r) -> Spine (Pf (Q r)) aux (TU r) t f = (MKQ t `As` pcon ("mkQ " ++ show t)) `Ap` (Pf (Fun t r) :| f) toSpine (Pf _) EMPTYQ = EMPTYQ `As` pcon "emptyQ" toSpine (Pf r) (UNION f g) = (UNION `As` pcon "union") `Ap` (Pf r :| f) `Ap` (Pf r :| g) toSpine (Pf func) (EXTQ f t g) = aux func f t g where aux :: Type (Q r) -> Pf (Q r) -> Type a -> Pf (a -> r) -> Spine (Pf (Q r)) aux (TU r) f t g = ((\x y -> EXTQ x t y) `As` pcon "extQ") `Ap` (Pf (TU r) :| f) `Ap` (Pf (Fun t r) :| g) toSpine (Pf r) (GMAPQ f) = (GMAPQ `As` pcon "gmapQ") `Ap` (Pf r :| f) toSpine (Pf r) (EVERYTHING f) = (EVERYTHING `As` pcon "everything") `Ap` (Pf r :| f) toSpine (Pf (Fun Any Any)) e = e `As` (pcon "") toSpine (Pf (Lns Any Any)) e = e `As` (pcon "") toSpine (Pf t) f = error $ "toSpine: " ++ show t ++ " " ++ safeShow f instance Show (Type a) where show Any = "Any" show (Id a) = showL["Id",show a] show Int = "Int" show Bool = "Bool" show Char = "Char" show One = "One" show (Either x y) = showL ["Either",show x,show y] show (Prod x y) = showL ["Prod",show x,show y] show (Fun x y) = showL ["Fun",show x,show y] show (Lns x y) = showL ["Lns",show x,show y] show (Data s f) = s show (Pf a) = showL ["Pf",show a] show (Dynamic) = "Dynamic" show TP = "TP" show (TU a) = showL ["TU",show a] instance Show Dynamic where show (Dyn t v) = gshow t v instance Show (Fctr f) where show I = "Id" show (K t) = showL ["K",show t] show L = "L" show (f:*!:g) = showL [show f,":*:",show g] show (f:+!:g) = showL [show f,":+:",show g] show (f:@!:g) = showL [show f,":@:",show g] instance Typeable a => Show (Pf a) where show = gshow typeof gshow :: Type a -> a -> String gshow (a@(Data s ((K One) :+!: ((K t) :*!: I)))) v = listify a t $ out v where listify :: Type a -> Type c -> Either One (c,a) -> String listify a c (Left _) = "[]" listify a c (Right (x,xs)) = gshow c x ++ ":" ++ gshow a xs gshow Dynamic (Dyn t x) = gshow t x gshow (Pf t) f@(COMP _ _ _) = "(" ++ showComp (Pf t) f ++ ")" gshow (Pf t) f@(COMP_LNS _ _ _) = "(" ++ showComp (Pf t) f ++ ")" gshow t x = showSpine (toSpine t x) where showSpine :: Spine a -> String showSpine (Ap f@(Ap (_ `As` c) (a :| x)) (b :| y)) | fixity c == Infix = showL [gshow a x,name c,gshow b y] | otherwise = showL [showSpine f,gshow b y] showSpine (_ `As` c) = name c showSpine (Ap f (t :| a)) = showL [showSpine f,gshow t a] showComp :: Type a -> a -> String showComp (Pf (Fun a c)) (COMP b f g) = showComp (Pf $ Fun b c) f ++ " . " ++ showComp (Pf $ Fun a b) g showComp (Pf (Lns a c)) (COMP_LNS b f g) = showComp (Pf $ Lns b c) f ++ " .< " ++ showComp (Pf $ Lns a b) g showComp t f = gshow t f safeShow :: Pf a -> String safeShow HOLE = "_L" safeShow TOP = "T" safeShow (FUN s f) = s safeShow (CONV e f) = showL ["conv",show e,safeShow f] safeShow (CONV_LNS e f) = showL ["lconv",show e,safeShow f] safeShow (LNS s l) = s safeShow (COMPF fctr _ f g) = showL ["compf",show fctr,safeShow f,safeShow g] safeShow (COMPF_LNS fctr _ f g) = showL ["compf_lns",show fctr,safeShow f,safeShow g] safeShow (PROTECT f) = showL ["protect",safeShow f] safeShow (PROTECT_LNS f) = showL ["protect_lns",safeShow f] safeShow (VAR s) = s safeShow (PNT v) = showL ["pnt"] safeShow BANG = "bang" safeShow (COMP _ f g) = showL [safeShow f,".",safeShow g] safeShow FST = "fst" safeShow SND = "snd" safeShow (SPLIT f g) = showL [safeShow f,"/\\",safeShow g] safeShow (PROD f g) = showL [safeShow f,"><",safeShow g] safeShow INL = "inl" safeShow INR = "inr" safeShow (EITHER f g) = showL [safeShow f,"\\/",safeShow g] safeShow (SUM f g) = showL [safeShow f,"-|-",safeShow g] safeShow ID = "id" safeShow SWAP = "swap" safeShow COSWAP = "coswap" safeShow DISTL = "distl" safeShow UNDISTL = "undistl" safeShow DISTR = "distr" safeShow UNDISTR = "undistr" safeShow ASSOCL = "assocl" safeShow ASSOCR = "assocr" safeShow COASSOCL = "coassocl" safeShow COASSOCR = "coassocr" safeShow INN = "inn" safeShow OUT = "out" safeShow (FMAP _ _ f) = showL ["fmap",safeShow f] safeShow (FZIP _ _ f) = showL ["fzip",safeShow f] safeShow (ANA f) = showL ["ana",safeShow f] safeShow (CATA f) = showL ["cata",safeShow f] safeShow (GET f) = showL ["get",safeShow f] safeShow (PUT f) = showL ["put",safeShow f] safeShow (CREATE f) = showL ["create",safeShow f] safeShow (COMP_LNS _ f g) = showL [safeShow f,".<",safeShow g] safeShow (FST_LNS v) = showL ["fst_lns",safeShow v] safeShow (SND_LNS v) = showL ["snd_lns",safeShow v] safeShow (PROD_LNS f g) = showL [safeShow f,"><<",safeShow g] safeShow (EITHER_LNS x f g) = showL [safeShow x,safeShow f,"\\/<",safeShow g] safeShow (SUM_LNS f g) = showL [safeShow f,"-|-<",safeShow g] safeShow (SUMW_LNS x y f g) = showL ["sum_lns",safeShow x,safeShow y,safeShow f,safeShow g] safeShow (BANG_LNS v) = showL ["bang_lns",safeShow v] safeShow (BANGL_LNS) = "bangl" safeShow (BANGR_LNS) = "bangr" safeShow ID_LNS = "id_lns" safeShow SWAP_LNS = "swap_lns" safeShow COSWAP_LNS = "coswap_lns" safeShow DISTL_LNS = "distl_lns" safeShow UNDISTL_LNS = "undistl_lns" safeShow DISTR_LNS = "distr_lns" safeShow UNDISTR_LNS = "undistr_lns" safeShow ASSOCL_LNS = "assocl_lns" safeShow ASSOCR_LNS = "assocr_lns" safeShow COASSOCL_LNS = "coassocl_lns" safeShow COASSOCR_LNS = "coassocr_lns" safeShow INN_LNS = "inn_lns" safeShow OUT_LNS = "out_lns" safeShow (FMAP_LNS _ _ f) = showL ["fmap",safeShow f] safeShow (ANA_LNS f) = showL ["ana_lns",safeShow f] safeShow (CATA_LNS f) = showL ["cata_lns",safeShow f] safeShow (MAP_LNS f) = showL ["map_lns",safeShow f] safeShow (LENGTH_LNS f) = showL ["length_lns"] safeShow FILTER_LEFT_LNS = "filter_left_lns" safeShow FILTER_RIGHT_LNS = "filter_right_lns" safeShow CAT_LNS = "cat_lns" safeShow CONCAT_LNS = "concat_lns" safeShow PLUS_LNS = "plus_lns" safeShow (SUML_LNS) = "suml_lns"