multirec 0.2 → 0.3
raw patch · 20 files changed
+436/−395 lines, 20 filesdep ~base
Dependency ranges changed: base
Files
- examples/ASTExamples.hs +4/−4
- examples/ASTUse.hs +24/−28
- examples/SingleExamples.hs +2/−1
- examples/SingleUse.hs +21/−19
- multirec.cabal +10/−7
- src/Generics/MultiRec.hs +1/−1
- src/Generics/MultiRec/Base.hs +42/−40
- src/Generics/MultiRec/Compos.hs +9/−9
- src/Generics/MultiRec/ConNames.hs +8/−8
- src/Generics/MultiRec/Constructor.hs +2/−2
- src/Generics/MultiRec/Eq.hs +31/−30
- src/Generics/MultiRec/Fold.hs +37/−41
- src/Generics/MultiRec/FoldAlg.hs +18/−27
- src/Generics/MultiRec/FoldAlgK.hs +19/−28
- src/Generics/MultiRec/FoldK.hs +35/−39
- src/Generics/MultiRec/HFix.hs +5/−4
- src/Generics/MultiRec/HFunctor.hs +31/−29
- src/Generics/MultiRec/Show.hs +27/−30
- src/Generics/MultiRec/TEq.hs +27/−0
- src/Generics/MultiRec/TH.hs +83/−48
examples/ASTExamples.hs view
@@ -31,9 +31,9 @@ renameVar :: Expr -> Expr renameVar = renameVar' Expr where- renameVar' :: Ix AST a => AST a -> a -> a+ renameVar' :: AST a -> a -> a renameVar' Var x = x ++ "_"- renameVar' _ x = compos renameVar' x+ renameVar' p x = compos renameVar' p x -- | Test for 'renameVar' @@ -90,12 +90,12 @@ -- | Evaluator eval1 :: Expr -> Env -> Int-eval1 x = let (EV f) = F.fold evalAlgebra1 x in f+eval1 x = let (EV f) = F.fold evalAlgebra1 Expr x in f -- | Evaluator eval2 :: Expr -> Env -> Int-eval2 x = let (EV f) = FA.fold evalAlgebra2 x in f+eval2 x = let (EV f) = FA.fold evalAlgebra2 Expr x in f -- | Test for 'eval1'
examples/ASTUse.hs view
@@ -64,41 +64,37 @@ :+: ( (K String) ) :>: Var --- ** 'Ix' instances--instance Ix AST Expr where-- from_ (Const i) = L (Tag (L (C (K i))))- from_ (Add e f) = L (Tag (R (L (C (I (I0 e) :*: I (I0 f))))))- from_ (Mul e f) = L (Tag (R (R (L (C (I (I0 e) :*: I (I0 f)))))))- from_ (EVar x) = L (Tag (R (R (R (L (C (I (I0 x))))))))- from_ (Let d e) = L (Tag (R (R (R (R (C (I (I0 d) :*: I (I0 e))))))))-- to_ (L (Tag (L (C (K i))))) = Const i- to_ (L (Tag (R (L (C (I (I0 e) :*: I (I0 f))))))) = Add e f- to_ (L (Tag (R (R (L (C (I (I0 e) :*: I (I0 f)))))))) = Mul e f- to_ (L (Tag (R (R (R (L (C (I (I0 x))))))))) = EVar x- to_ (L (Tag (R (R (R (R (C (I (I0 d) :*: I (I0 e))))))))) = Let d e+-- ** 'El' instances - index = Expr+instance El AST Expr where proof = Expr+instance El AST Decl where proof = Decl+instance El AST Var where proof = Var -instance Ix AST Decl where+-- ** 'Fam' instance - from_ (x := e) = R (L (Tag (L (C (I (I0 x) :*: I (I0 e))))))- from_ (Seq c d) = R (L (Tag (R (L (C (I (I0 c) :*: I (I0 d)))))))- from_ (None) = R (L (Tag (R (R (C U)))))+instance Fam AST where - to_ (R (L (Tag (L (C (I (I0 x) :*: I (I0 e))))))) = x := e- to_ (R (L (Tag (R (L (C (I (I0 c) :*: I (I0 d)))))))) = Seq c d- to_ (R (L (Tag (R (R (C U)))))) = None+ from Expr (Const i) = L (Tag (L (C (K i))))+ from Expr (Add e f) = L (Tag (R (L (C (I (I0 e) :*: I (I0 f))))))+ from Expr (Mul e f) = L (Tag (R (R (L (C (I (I0 e) :*: I (I0 f)))))))+ from Expr (EVar x) = L (Tag (R (R (R (L (C (I (I0 x))))))))+ from Expr (Let d e) = L (Tag (R (R (R (R (C (I (I0 d) :*: I (I0 e)))))))) - index = Decl+ from Decl (x := e) = R (L (Tag (L (C (I (I0 x) :*: I (I0 e))))))+ from Decl (Seq c d) = R (L (Tag (R (L (C (I (I0 c) :*: I (I0 d)))))))+ from Decl (None) = R (L (Tag (R (R (C U))))) -instance Ix AST Var where+ from Var x = R (R (Tag (K x))) - from_ x = R (R (Tag (K x)))+ to Expr (L (Tag (L (C (K i))))) = Const i+ to Expr (L (Tag (R (L (C (I (I0 e) :*: I (I0 f))))))) = Add e f+ to Expr (L (Tag (R (R (L (C (I (I0 e) :*: I (I0 f)))))))) = Mul e f+ to Expr (L (Tag (R (R (R (L (C (I (I0 x))))))))) = EVar x+ to Expr (L (Tag (R (R (R (R (C (I (I0 d) :*: I (I0 e))))))))) = Let d e - to_ (R (R (Tag (K x)))) = x+ to Decl (R (L (Tag (L (C (I (I0 x) :*: I (I0 e))))))) = x := e+ to Decl (R (L (Tag (R (L (C (I (I0 c) :*: I (I0 d)))))))) = Seq c d+ to Decl (R (L (Tag (R (R (C U)))))) = None - index = Var+ to Var (R (R (Tag (K x)))) = x
examples/SingleExamples.hs view
@@ -8,12 +8,13 @@ -- Replace SingleUse with SingleTHUse below if you want -- to test TH code generation. import SingleUse+-- import SingleTHUse import Single -- | evalLogic takes a function that gives a logic values to variables, -- | and a Logic expression, and evaluates it. evalLogic :: (String -> Bool) -> Logic -> Bool-evalLogic env = fold algebra +evalLogic env = fold algebra Logic where algebra :: Algebra LogicF Bool algebra _ = env & impl & (==) & (&&) & (||) & not & True & False
examples/SingleUse.hs view
@@ -62,26 +62,28 @@ :+: C F U ) :>: Logic --- ** 'Ix' instances+-- ** 'El' instance -instance Ix LogicF Logic where+instance El LogicF Logic where proof = Logic - from_ (Var s) = Tag (L (C (K s)))- from_ (l1 :->: l2) = Tag (R (L (C (I (I0 l1) :*: I (I0 l2)))))- from_ (l1 :<->: l2) = Tag (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))- from_ (l1 :&&: l2) = Tag (R (R (R (L (C (I (I0 l1) :*: I (I0 l2)))))))- from_ (l1 :||: l2) = Tag (R (R (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))))- from_ (Not l) = Tag (R (R (R (R (R (L (C (I (I0 l)))))))))- from_ T = Tag (R (R (R (R (R (R (L (C U))))))))- from_ F = Tag (R (R (R (R (R (R (R (C U))))))))+-- ** 'Fam' instance - to_ (Tag (L (C (K s)))) = Var s- to_ (Tag (R (L (C (I (I0 l1) :*: I (I0 l2)))))) = l1 :->: l2- to_ (Tag (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))) = l1 :<->: l2- to_ (Tag (R (R (R (L (C (I (I0 l1) :*: I (I0 l2)))))))) = l1 :&&: l2- to_ (Tag (R (R (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))))) = l1 :||: l2- to_ (Tag (R (R (R (R (R (L (C (I (I0 l)))))))))) = Not l- to_ (Tag (R (R (R (R (R (R (L (C U))))))))) = T- to_ (Tag (R (R (R (R (R (R (R (C U))))))))) = F+instance Fam LogicF where - index = Logic+ from Logic (Var s) = Tag (L (C (K s)))+ from Logic (l1 :->: l2) = Tag (R (L (C (I (I0 l1) :*: I (I0 l2)))))+ from Logic (l1 :<->: l2) = Tag (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))+ from Logic (l1 :&&: l2) = Tag (R (R (R (L (C (I (I0 l1) :*: I (I0 l2)))))))+ from Logic (l1 :||: l2) = Tag (R (R (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))))+ from Logic (Not l) = Tag (R (R (R (R (R (L (C (I (I0 l)))))))))+ from Logic T = Tag (R (R (R (R (R (R (L (C U))))))))+ from Logic F = Tag (R (R (R (R (R (R (R (C U))))))))++ to Logic (Tag (L (C (K s)))) = Var s+ to Logic (Tag (R (L (C (I (I0 l1) :*: I (I0 l2)))))) = l1 :->: l2+ to Logic (Tag (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))) = l1 :<->: l2+ to Logic (Tag (R (R (R (L (C (I (I0 l1) :*: I (I0 l2)))))))) = l1 :&&: l2+ to Logic (Tag (R (R (R (R (L (C (I (I0 l1) :*: I (I0 l2))))))))) = l1 :||: l2+ to Logic (Tag (R (R (R (R (R (L (C (I (I0 l)))))))))) = Not l+ to Logic (Tag (R (R (R (R (R (R (L (C U))))))))) = T+ to Logic (Tag (R (R (R (R (R (R (R (C U))))))))) = F
multirec.cabal view
@@ -1,5 +1,5 @@ name: multirec-version: 0.2+version: 0.3 license: BSD3 license-file: LICENSE author: Alexey Rodriguez,@@ -8,7 +8,7 @@ Johan Jeuring maintainer: generics@haskell.org category: Generics-synopsis: Generic programming with systems of recursive datatypes+synopsis: Generic programming for families of recursive datatypes homepage: http://www.cs.uu.nl/wiki/GenericProgramming/Multirec description: Many generic programs require information about the recursive positions@@ -16,16 +16,16 @@ the Zipper data structure. Several generic programming systems allow to write such functions by viewing datatypes as fixed points of a pattern functor. Traditionally, this view has been limited to so-called regular- datatypes such as lists and binary trees. In particular, systems of+ datatypes such as lists and binary trees. In particular, families of mutually recursive datatypes have been excluded. . With the multirec library, we provide a mechanism to talk about fixed- points of systems of datatypes that may be mutually recursive. On top+ points of families of datatypes that may be mutually recursive. On top of this representations, generic functions such as the fold or the Zipper can then be defined. . We expect that the library will be especially interesting for compiler- writers, because ASTs are typically systems of mutually recursive datatypes,+ writers, because ASTs are typically families of mutually recursive datatypes, and with multirec it becomes easy to write generic functions on ASTs. . The library is based on ideas described in the paper:@@ -38,7 +38,7 @@ stability: experimental build-type: Simple cabal-version: >= 1.2.1-tested-with: GHC == 6.8.3, GHC == 6.10.1+tested-with: GHC == 6.8.3, GHC == 6.10.3 hs-source-dirs: src exposed-modules: Generics.MultiRec @@ -59,6 +59,9 @@ Generics.MultiRec.Eq Generics.MultiRec.Show + -- Extra+ Generics.MultiRec.TEq+ extra-source-files: examples/AST.hs examples/ASTUse.hs examples/ASTTHUse.hs@@ -68,5 +71,5 @@ examples/SingleTHUse.hs examples/SingleExamples.hs CREDITS-build-depends: base >= 3.0 && < 4,+build-depends: base >= 3.0 && < 5, template-haskell >= 2.2 && < 2.4
src/Generics/MultiRec.hs view
@@ -9,7 +9,7 @@ -- Portability : non-portable -- -- multirec ----- generic programming with systems of recursive datatypes+-- generic programming for families of recursive datatypes -- -- This top-level module re-exports all other modules of the library. --
src/Generics/MultiRec/Base.hs view
@@ -17,9 +17,9 @@ -- Portability : non-portable -- -- This module is the base of the multirec library. It defines the view of a--- system of datatypes: All the datatypes of the system are represented as+-- family of datatypes: All the datatypes of the family are represented as -- indexed functors that are built up from the structure types defined in this--- module. Furthermore, in order to use the library for a system, conversion+-- module. Furthermore, in order to use the library for a family, conversion -- functions have to be defined between the original datatypes and their -- representation. The type class that holds these conversion functions are -- also defined here.@@ -28,7 +28,7 @@ module Generics.MultiRec.Base (-- * Structure types- I(..), unI,+ I(..), K(..), U(..), (:+:)(..), (:*:)(..), (:>:)(..), unTag, C(..), unC,@@ -39,12 +39,17 @@ -- ** Unlifted variants I0(..), K0(..), - -- * Indexed systems- PF, Str, Ix(..)+ -- * Indexed families+ PF, El(..), Fam(..), index,++ -- ** Equality for indexed families+ module Generics.MultiRec.TEq,+ EqS(..) ) where import Control.Applicative import Generics.MultiRec.Constructor+import Generics.MultiRec.TEq -- * Structure types @@ -53,41 +58,36 @@ infixr 7 :*: -- | Represents recursive positions. The first argument indicates--- which type (within the system) to recurse on.-data I :: * -> (* -> *) -> (* -> *) -> * -> * where- I :: Ix s xi => r xi -> I xi s r ix---- | Destructor for 'I'.-unI :: I xi s r ix -> r xi-unI (I x) = x+-- which type to recurse on.+data I xi (r :: * -> *) ix = I {unI :: r xi} --- | Represents constant types that do not belong to the system.-data K a (s :: * -> *) (r :: * -> *) ix = K {unK :: a}+-- | Represents constant types that do not belong to the family.+data K a (r :: * -> *) ix = K {unK :: a} -- | Represents constructors without fields.-data U (s :: * -> *) (r :: * -> *) ix = U+data U (r :: * -> *) ix = U -- | Represents sums (choices between constructors).-data (f :+: g) (s :: * -> *) (r :: * -> *) ix = L (f s r ix) | R (g s r ix)+data (f :+: g) (r :: * -> *) ix = L (f r ix) | R (g r ix) -- | Represents products (sequences of fields of a constructor).-data (f :*: g) (s :: * -> *) (r :: * -> *) ix = f s r ix :*: g s r ix+data (f :*: g) (r :: * -> *) ix = f r ix :*: g r ix --- | Is used to indicate the type (within the system) that a+-- | Is used to indicate the type that a -- particular constructor injects to.-data (:>:) :: ((* -> *) -> (* -> *) -> * -> *) -> * -> (* -> *) -> (* -> *) -> * -> * where- Tag :: f s r ix -> (f :>: ix) s r ix+data f :>: ix :: (* -> *) -> * -> * where+ Tag :: f r ix -> (f :>: ix) r ix -- | Destructor for '(:>:)'.-unTag :: (f :>: ix) s r ix -> f s r ix+unTag :: (f :>: ix) r ix -> f r ix unTag (Tag x) = x -- | Represents constructors.-data C c f (s :: * -> *) (r :: * -> *) ix where- C :: (Constructor c) => f s r ix -> C c f s r ix+data C c f (r :: * -> *) ix where+ C :: f r ix -> C c f r ix -- | Destructor for 'C'.-unC :: C c f s r ix -> f s r ix+unC :: C c f r ix -> f r ix unC (C x) = x -- ** Unlifted variants@@ -108,23 +108,25 @@ instance Functor (K0 a) where fmap f = K0 . unK0 --- * Indexed systems+-- * Indexed families --- | Type family describing the pattern functor of a system.-type family PF s :: (* -> *) -> (* -> *) -> * -> *-type Str s ix = (PF s) s I0 ix+-- | Type family describing the pattern functor of a family.+type family PF phi :: (* -> *) -> * -> * -class Ix s ix where- from_ :: ix -> Str s ix- to_ :: Str s ix -> ix+-- | Class for the members of a family.+class El phi ix where+ proof :: phi ix - -- | Some functions need to have their types desugared in order to make programs- -- that use them typable. Desugaring consists in transforming ``inline'' type- -- family applications into equality constraints. This is a strangeness in current- -- versions of GHC that hopefully will be fixed sometime in the future.- from :: (pfs ~ PF s) => ix -> pfs s I0 ix- from = from_- to :: (pfs ~ PF s) => pfs s I0 ix -> ix- to = to_+-- | For backwards-compatibility: a synonym for 'proof'.+index :: El phi ix => phi ix+index = proof - index :: s ix+-- | Class that contains the shallow conversion functions for a family.+class Fam phi where+ from :: phi ix -> ix -> PF phi I0 ix+ to :: phi ix -> PF phi I0 ix -> ix++-- | Semi-decidable equality for types of a family.+class EqS phi where+ eqS :: phi ix -> phi ix' -> Maybe (ix :=: ix')+
src/Generics/MultiRec/Compos.hs view
@@ -30,16 +30,16 @@ -- * Compos -- | Normal version.-compos :: (Ix s ix, HFunctor (PF s)) =>- (forall ix. Ix s ix => s ix -> ix -> ix) -> ix -> ix-compos f = to . hmap (\ ix -> I0 . f ix . unI0) . from+compos :: (Fam phi, HFunctor phi (PF phi)) =>+ (forall ix. phi ix -> ix -> ix) -> phi ix -> ix -> ix+compos f p = to p . hmap (\ p -> I0 . f p . unI0) . from p -- | Monadic version of 'compos'.-composM :: (Ix s ix, HFunctor (PF s), Monad m) =>- (forall ix. Ix s ix => s ix -> ix -> m ix) -> ix -> m ix-composM f = liftM to . hmapM (\ ix -> liftM I0 . f ix . unI0) . from+composM :: (Fam phi, HFunctor phi (PF phi), Monad m) =>+ (forall ix. phi ix -> ix -> m ix) -> phi ix -> ix -> m ix+composM f p = liftM (to p) . hmapM (\ p -> liftM I0 . f p . unI0) . from p -- | Applicative version of 'compos'.-composA :: (Ix s ix, HFunctor (PF s), Applicative a) =>- (forall ix. Ix s ix => s ix -> ix -> a ix) -> ix -> a ix-composA f = liftA to . hmapA (\ ix -> liftA I0 . f ix . unI0) . from+composA :: (Fam phi, HFunctor phi (PF phi), Applicative a) =>+ (forall ix. phi ix -> ix -> a ix) -> phi ix -> ix -> a ix+composA f p = liftA (to p) . hmapA (\ p -> liftA I0 . f p . unI0) . from p
src/Generics/MultiRec/ConNames.hs view
@@ -15,7 +15,7 @@ -- Stability : experimental -- Portability : non-portable ----- Generic function that returns the constructor names available in a system+-- Generic function that returns the constructor names available in a family -- of datatypes. -- -----------------------------------------------------------------------------@@ -25,15 +25,15 @@ import Generics.MultiRec.Base import Generics.MultiRec.Constructor -class ConNames (f :: (* -> *) -> (* -> *) -> * -> *) where- hconNames :: f s r ix -> [String]+class ConNames (f :: (* -> *) -> * -> *) where+ hconNames :: f r ix -> [String] instance Constructor c => ConNames (C c f) where hconNames c = [conName c] instance (ConNames f, ConNames g) => ConNames (f :+: g) where- hconNames (_ :: (f :+: g) r s ix) = hconNames (undefined :: f r s ix) ++- hconNames (undefined :: g r s ix)+ hconNames (_ :: (f :+: g) r ix) = hconNames (undefined :: f r ix) +++ hconNames (undefined :: g r ix) instance ConNames (K x) where hconNames _ = []@@ -48,7 +48,7 @@ hconNames _ = [] instance (ConNames f) => ConNames (f :>: ix) where- hconNames (_ :: (f :>: ix) r s xi) = hconNames (undefined :: f r s ix)+ hconNames (_ :: (f :>: ix) r xi) = hconNames (undefined :: f r ix) -conNames :: forall s ix . (Ix s ix, ConNames (PF s)) => s ix -> [String]-conNames s = hconNames (undefined :: PF s s I0 ix)+conNames :: forall phi ix . (ConNames (PF phi)) => phi ix -> [String]+conNames _ = hconNames (undefined :: PF phi I0 ix)
src/Generics/MultiRec/Constructor.hs view
@@ -24,8 +24,8 @@ -- The weird argument is supposed to be instantiated with 'C' from -- base, hence the complex kind. class Constructor c where- conName :: t c (f :: (* -> *) -> (* -> *) -> * -> *) (s :: * -> *) (r :: * -> *) ix -> String- conFixity :: t c (f :: (* -> *) -> (* -> *) -> * -> *) (s :: * -> *) (r :: * -> *) ix -> Fixity+ conName :: t c (f :: (* -> *) -> * -> *) (r :: * -> *) ix -> String+ conFixity :: t c (f :: (* -> *) -> * -> *) (r :: * -> *) ix -> Fixity conFixity = const Prefix -- | Datatype to represent the fixity of a constructor. An infix declaration
src/Generics/MultiRec/Eq.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- |@@ -22,52 +24,51 @@ -- * Generic equality -class HEq f where- heq :: s ix ->- (forall ix. Ix s ix => s ix -> r ix -> r ix -> Bool) ->- f s r ix -> f s r ix -> Bool+class HEq phi f where+ heq :: (forall ix. phi ix -> r ix -> r ix -> Bool) ->+ phi ix -> f r ix -> f r ix -> Bool -instance HEq (I xi) where- heq _ eq (I x1) (I x2) = eq index x1 x2+instance El phi xi => HEq phi (I xi) where+ heq eq _ (I x1) (I x2) = eq proof x1 x2 -- | For constant types, we make use of the standard -- equality function.-instance Eq x => HEq (K x) where- heq _ eq (K x1) (K x2) = x1 == x2+instance Eq a => HEq phi (K a) where+ heq eq _ (K x1) (K x2) = x1 == x2 -instance HEq U where- heq _ eq U U = True+instance HEq phi U where+ heq eq _ U U = True -instance (HEq f, HEq g) => HEq (f :+: g) where- heq ix eq (L x1) (L x2) = heq ix eq x1 x2- heq ix eq (R y1) (R y2) = heq ix eq y1 y2- heq _ eq _ _ = False+instance (HEq phi f, HEq phi g) => HEq phi (f :+: g) where+ heq eq p (L x1) (L x2) = heq eq p x1 x2+ heq eq p (R y1) (R y2) = heq eq p y1 y2+ heq eq _ _ _ = False -instance (HEq f, HEq g) => HEq (f :*: g) where- heq ix eq (x1 :*: y1) (x2 :*: y2) = heq ix eq x1 x2 && heq ix eq y1 y2+instance (HEq phi f, HEq phi g) => HEq phi (f :*: g) where+ heq eq p (x1 :*: y1) (x2 :*: y2) = heq eq p x1 x2 && heq eq p y1 y2 -- The following instance does not compile with ghc-6.8.2-instance HEq f => HEq (f :>: ix) where- heq ix eq (Tag x1) (Tag x2) = heq ix eq x1 x2+instance HEq phi f => HEq phi (f :>: ix) where+ heq eq p (Tag x1) (Tag x2) = heq eq p x1 x2 -instance HEq f => HEq (C c f) where- heq ix eq (C x1) (C x2) = heq ix eq x1 x2+instance (Constructor c, HEq phi f) => HEq phi (C c f) where+ heq eq p (C x1) (C x2) = heq eq p x1 x2 -eq :: (Ix s ix, HEq (PF s)) => s ix -> ix -> ix -> Bool-eq ix x1 x2 = heq ix (\ ix (I0 x1) (I0 x2) -> eq ix x1 x2) (from x1) (from x2)+eq :: (Fam phi, HEq phi (PF phi)) => phi ix -> ix -> ix -> Bool+eq p x1 x2 = heq (\ p (I0 x1) (I0 x2) -> eq p x1 x2) p (from p x1) (from p x2) -- Note: -- -- We do not declare an equality instance such as ----- instance (Ix s ix, HEq (PF s)) => Eq ix where--- (==) = eq index+-- instance (El phi ix, HEq phi (PF phi)) => Eq ix where+-- (==) = eq proof ----- because "s" is not mentioned on the right hand side.--- One datatype may belong to multiple systems, and+-- because "phi" is not mentioned on the right hand side.+-- One datatype may belong to multiple families, and -- although the generic equality instances should be -- the same, there is no good way to decide which instance -- to use. ----- For a concrete "s", it is still possible to manually+-- For a concrete "phi", it is still possible to manually -- define an "Eq" instance as above.
src/Generics/MultiRec/Fold.hs view
@@ -25,7 +25,8 @@ -- * for folds with constant return type, look at -- "Generics.MultiRec.FoldAlgK" (or "Generics.MultiRec.FoldK"), ----- * for other folds, look at "Generics.MultiRec.FoldAlg".+-- * for folds with convenient algebras, look at+-- "Generics.MultiRec.FoldAlg". -- ----------------------------------------------------------------------------- @@ -39,64 +40,59 @@ -- * Generic fold and unfold -type Algebra' s f r = forall ix. Ix s ix => s ix -> f s r ix -> r ix-type Algebra s r = Algebra' s (PF s) r-type AlgebraF' s f g r = forall ix. Ix s ix => s ix -> f s r ix -> g (r ix)-type AlgebraF s g r = AlgebraF' s (PF s) g r+type Algebra' phi f r = forall ix. phi ix -> f r ix -> r ix+type Algebra phi r = Algebra' phi (PF phi) r+type AlgebraF' phi f g r = forall ix. phi ix -> f r ix -> g (r ix)+type AlgebraF phi g r = AlgebraF' phi (PF phi) g r -fold :: (Ix s ix, HFunctor (PF s)) =>- Algebra s r -> ix -> r ix-fold f = f index . hmap (\ _ (I0 x) -> fold f x) . from+fold :: (Fam phi, HFunctor phi (PF phi)) =>+ Algebra phi r -> phi ix -> ix -> r ix+fold f p = f p . hmap (\ p (I0 x) -> fold f p x) . from p -foldM :: (Ix s ix, HFunctor (PF s), Monad m) =>- AlgebraF s m r -> ix -> m (r ix)-foldM f x = hmapM (\ _ (I0 x) -> foldM f x) (from x) >>= f index+foldM :: (Fam phi, HFunctor phi (PF phi), Monad m) =>+ AlgebraF phi m r -> phi ix -> ix -> m (r ix)+foldM f p x = hmapM (\ p (I0 x) -> foldM f p x) (from p x) >>= f p -type CoAlgebra' s f r = forall ix. Ix s ix => s ix -> r ix -> f s r ix-type CoAlgebra s r = CoAlgebra' s (PF s) r-type CoAlgebraF' s f g r = forall ix. Ix s ix => s ix -> r ix -> g (f s r ix)-type CoAlgebraF s g r = CoAlgebraF' s (PF s) g r+type CoAlgebra' phi f r = forall ix. phi ix -> r ix -> f r ix+type CoAlgebra phi r = CoAlgebra' phi (PF phi) r+type CoAlgebraF' phi f g r = forall ix. phi ix -> r ix -> g (f r ix)+type CoAlgebraF phi g r = CoAlgebraF' phi (PF phi) g r -unfold :: (Ix s ix, HFunctor (PF s)) =>- CoAlgebra s r -> r ix -> ix-unfold f = to . hmap (\ _ x -> I0 (unfold f x)) . f index+unfold :: (Fam phi, HFunctor phi (PF phi)) =>+ CoAlgebra phi r -> phi ix -> r ix -> ix+unfold f p = to p . hmap (\ p x -> I0 (unfold f p x)) . f p -unfoldM :: (Ix s ix, HFunctor (PF s), Monad m) =>- CoAlgebraF s m r -> r ix -> m ix-unfoldM f x = f index x >>= liftMto . hmapM (\ _ x -> liftM I0 (unfoldM f x))- where- -- only for ghc-6.8.3 compatibility- liftMto :: (Monad m, Ix s ix, pfs ~ PF s) => m (pfs s I0 ix) -> m ix- liftMto = liftM to+unfoldM :: (Fam phi, HFunctor phi (PF phi), Monad m) =>+ CoAlgebraF phi m r -> phi ix -> r ix -> m ix+unfoldM f p x = f p x >>= liftM (to p) . hmapM (\ p x -> liftM I0 (unfoldM f p x)) -type ParaAlgebra' s f r = forall ix. Ix s ix => s ix -> f s r ix -> ix -> r ix-type ParaAlgebra s r = ParaAlgebra' s (PF s) r-type ParaAlgebraF' s f g r = forall ix. Ix s ix => s ix -> f s r ix -> ix -> g (r ix)-type ParaAlgebraF s g r = ParaAlgebraF' s (PF s) g r+type ParaAlgebra' phi f r = forall ix. phi ix -> f r ix -> ix -> r ix+type ParaAlgebra phi r = ParaAlgebra' phi (PF phi) r+type ParaAlgebraF' phi f g r = forall ix. phi ix -> f r ix -> ix -> g (r ix)+type ParaAlgebraF phi g r = ParaAlgebraF' phi (PF phi) g r -para :: (Ix s ix, HFunctor (PF s)) => - ParaAlgebra s r -> ix -> r ix-para f x = f index (hmap (\ _ (I0 x) -> para f x) (from x)) x+para :: (Fam phi, HFunctor phi (PF phi)) => + ParaAlgebra phi r -> phi ix -> ix -> r ix+para f p x = f p (hmap (\ p (I0 x) -> para f p x) (from p x)) x -paraM :: (Ix s ix, HFunctor (PF s), Monad m) => - ParaAlgebraF s m r -> ix -> m (r ix)-paraM f x = hmapM (\ _ (I0 x) -> paraM f x) (from x) >>= \ r -> f index r x+paraM :: (Fam phi, HFunctor phi (PF phi), Monad m) => + ParaAlgebraF phi m r -> phi ix -> ix -> m (r ix)+paraM f p x = hmapM (\ p (I0 x) -> paraM f p x) (from p x) >>= \ r -> f p r x -- * Creating an algebra infixr 5 & infixr :-> -type AlgPart a (s :: * -> *) r ix = a s r ix -> r ix-type (f :-> g) (s :: * -> *) (r :: * -> *) ix = f s r ix -> g s r ix+type AlgPart f r ix = f r ix -> r ix+type (f :-> g) (r :: * -> *) ix = f r ix -> g r ix -(&) :: (AlgPart a :-> AlgPart b :-> AlgPart (a :+: b)) s r ix+(&) :: (AlgPart a :-> AlgPart b :-> AlgPart (a :+: b)) r ix (f & g) (L x) = f x (f & g) (R x) = g x -tag :: AlgPart a s r ix -> AlgPart (a :>: ix) s r ix'+tag :: AlgPart a r ix -> AlgPart (a :>: ix) r ix' tag f (Tag x) = f x -con :: AlgPart a s r ix -> AlgPart (C c a) s r ix+con :: AlgPart a r ix -> AlgPart (C c a) r ix con f (C x) = f x-
src/Generics/MultiRec/FoldAlg.hs view
@@ -30,51 +30,50 @@ -- * The type family of convenient algebras. -- | The type family we use to describe the convenient algebras.-type family Alg (f :: (* -> *) -> (* -> *) -> * -> *) - (s :: * -> *) -- system+type family Alg (f :: (* -> *) -> * -> *) (r :: * -> *) -- recursive positions (ix :: *) -- index :: * -- | For a constant, we take the constant value to a result.-type instance Alg (K a) (s :: * -> *) (r :: * -> *) ix = a -> r ix+type instance Alg (K a) (r :: * -> *) ix = a -> r ix -- | For a unit, no arguments are available.-type instance Alg U (s :: * -> *) (r :: * -> *) ix = r ix+type instance Alg U (r :: * -> *) ix = r ix -- | For an identity, we turn the recursive result into a final result. -- Note that the index can change.-type instance Alg (I xi) (s :: * -> *) r ix = r xi -> r ix+type instance Alg (I xi) r ix = r xi -> r ix -- | For a sum, the algebra is a pair of two algebras.-type instance Alg (f :+: g) s r ix = (Alg f s r ix, Alg g s r ix)+type instance Alg (f :+: g) r ix = (Alg f r ix, Alg g r ix) -- | For a product where the left hand side is a constant, we -- take the value as an additional argument.-type instance Alg (K a :*: g) s r ix = a -> Alg g s r ix+type instance Alg (K a :*: g) r ix = a -> Alg g r ix -- | For a product where the left hand side is an identity, we -- take the recursive result as an additional argument.-type instance Alg (I xi :*: g) s r ix = r xi -> Alg g s r ix+type instance Alg (I xi :*: g) r ix = r xi -> Alg g r ix -- | A tag changes the index of the final result.-type instance Alg (f :>: xi) s r ix = Alg f s r xi+type instance Alg (f :>: xi) r ix = Alg f r xi -- | Constructors are ignored.-type instance Alg (C c f) s r ix = Alg f s r ix+type instance Alg (C c f) r ix = Alg f r ix -- | The algebras passed to the fold have to work for all index types--- in the system. The additional witness argument is required only+-- in the family. The additional witness argument is required only -- to make GHC's typechecker happy.-type Algebra s r = forall ix. Ix s ix => s ix -> Alg (PF s) s r ix+type Algebra phi r = forall ix. phi ix -> Alg (PF phi) r ix -- * The class to turn convenient algebras into standard algebras. -- | The class fold explains how to convert a convenient algebra -- 'Alg' back into a function from functor to result, as required -- by the standard fold function.-class Fold (f :: (* -> *) -> (* -> *) -> * -> *) where- alg :: (Ix s ix) => Alg f s r ix -> f s r ix -> r ix+class Fold (f :: (* -> *) -> * -> *) where+ alg :: Alg f r ix -> f r ix -> r ix instance Fold (K a) where alg f (K x) = f x@@ -103,20 +102,12 @@ -- * Interface --- | Variant of fold that takes an additional witness argument.-fold_ :: forall s ix r . (Ix s ix, HFunctor (PF s), Fold (PF s)) =>- s ix ->- Algebra s r ->- ix -> r ix-fold_ ix f = (alg :: Alg (PF s) s r ix -> (PF s) s r ix -> r ix) (f ix) .- hmap (\ _ (I0 x) -> fold_ index f x) .- from- -- | Fold with convenient algebras.-fold :: forall s ix r . (Ix s ix, HFunctor (PF s), Fold (PF s)) =>- Algebra s r ->- ix -> r ix-fold = fold_ index+fold :: forall phi ix r . (Fam phi, HFunctor phi (PF phi), Fold (PF phi)) =>+ Algebra phi r -> phi ix -> ix -> r ix+fold f p = alg (f p) .+ hmap (\ p (I0 x) -> fold f p x) .+ from p -- * Construction of algebras
src/Generics/MultiRec/FoldAlgK.hs view
@@ -30,50 +30,49 @@ -- * The type family of convenient algebras. -- | The type family we use to describe the convenient algebras.-type family Alg (f :: (* -> *) -> (* -> *) -> * -> *) - (s :: * -> *) -- system+type family Alg (f :: (* -> *) -> * -> *) (r :: *) -- result type :: * -- | For a constant, we take the constant value to a result.-type instance Alg (K a) (s :: * -> *) r = a -> r+type instance Alg (K a) r = a -> r -- | For a unit, no arguments are available.-type instance Alg U (s :: * -> *) r = r+type instance Alg U r = r -- | For an identity, we turn the recursive result into a final result. -- Note that the index can change.-type instance Alg (I xi) (s :: * -> *) r = r -> r+type instance Alg (I xi) r = r -> r -- | For a sum, the algebra is a pair of two algebras.-type instance Alg (f :+: g) s r = (Alg f s r, Alg g s r)+type instance Alg (f :+: g) r = (Alg f r, Alg g r) -- | For a product where the left hand side is a constant, we -- take the value as an additional argument.-type instance Alg (K a :*: g) s r = a -> Alg g s r+type instance Alg (K a :*: g) r = a -> Alg g r -- | For a product where the left hand side is an identity, we -- take the recursive result as an additional argument.-type instance Alg (I xi :*: g) s r = r -> Alg g s r+type instance Alg (I xi :*: g) r = r -> Alg g r --- | A tag changes the index of the final result.-type instance Alg (f :>: xi) s r = Alg f s r+-- | Tags are ignored.+type instance Alg (f :>: xi) r = Alg f r -- | Constructors are ignored.-type instance Alg (C c f) s r = Alg f s r+type instance Alg (C c f) r = Alg f r -- | The algebras passed to the fold have to work for all index types--- in the system. The additional witness argument is required only+-- in the family. The additional witness argument is required only -- to make GHC's typechecker happy.-type Algebra s r = forall ix. Ix s ix => s ix -> Alg (PF s) s r+type Algebra phi r = forall ix. phi ix -> Alg (PF phi) r -- * The class to turn convenient algebras into standard algebras. -- | The class fold explains how to convert a convenient algebra -- 'Alg' back into a function from functor to result, as required -- by the standard fold function.-class Fold (f :: (* -> *) -> (* -> *) -> * -> *) where- alg :: (Ix s ix) => Alg f s r -> f s (K0 r) ix -> r+class Fold (f :: (* -> *) -> * -> *) where+ alg :: Alg f r -> f (K0 r) ix -> r instance Fold (K a) where alg f (K x) = f x@@ -102,20 +101,12 @@ -- * Interface --- | Variant of fold that takes an additional witness argument.-fold_ :: forall s ix r . (Ix s ix, HFunctor (PF s), Fold (PF s)) =>- s ix ->- Algebra s r ->- ix -> r-fold_ ix f = (alg :: Alg (PF s) s r -> (PF s) s (K0 r) ix -> r) (f ix) .- hmap (\ _ (I0 x) -> K0 (fold_ index f x)) .- from- -- | Fold with convenient algebras.-fold :: forall s ix r . (Ix s ix, HFunctor (PF s), Fold (PF s)) =>- Algebra s r ->- ix -> r-fold = fold_ index+fold :: forall phi ix r . (Fam phi, HFunctor phi (PF phi), Fold (PF phi)) =>+ Algebra phi r -> phi ix -> ix -> r+fold f p = alg (f p) .+ hmap (\ p (I0 x) -> K0 (fold f p x)) .+ from p -- * Construction of algebras
src/Generics/MultiRec/FoldK.hs view
@@ -31,63 +31,59 @@ -- * Generic fold and unfold -type Algebra' s f r = forall ix. Ix s ix => s ix -> f s (K0 r) ix -> r-type Algebra s r = Algebra' s (PF s) r-type AlgebraF' s f g r = forall ix. Ix s ix => s ix -> f s (K0 r) ix -> g r-type AlgebraF s g r = AlgebraF' s (PF s) g r+type Algebra' phi f r = forall ix. phi ix -> f (K0 r) ix -> r+type Algebra phi r = Algebra' phi (PF phi) r+type AlgebraF' phi f g r = forall ix. phi ix -> f (K0 r) ix -> g r+type AlgebraF phi g r = AlgebraF' phi (PF phi) g r -fold :: (Ix s ix, HFunctor (PF s)) =>- Algebra s r -> ix -> r-fold f = f index . hmap (\ _ (I0 x) -> K0 (fold f x)) . from+fold :: (Fam phi, HFunctor phi (PF phi)) =>+ Algebra phi r -> phi ix -> ix -> r+fold f p = f p . hmap (\ p (I0 x) -> K0 (fold f p x)) . from p -foldM :: (Ix s ix, HFunctor (PF s), Monad m) =>- AlgebraF s m r -> ix -> m r-foldM f x = hmapM (\ _ (I0 x) -> liftM K0 (foldM f x)) (from x) >>= f index+foldM :: (Fam phi, HFunctor phi (PF phi), Monad m) =>+ AlgebraF phi m r -> phi ix -> ix -> m r+foldM f p x = hmapM (\ p (I0 x) -> liftM K0 (foldM f p x)) (from p x) >>= f p -type CoAlgebra' s f r = forall ix. Ix s ix => s ix -> r -> f s (K0 r) ix-type CoAlgebra s r = CoAlgebra' s (PF s) r-type CoAlgebraF' s f g r = forall ix. Ix s ix => s ix -> r -> g (f s (K0 r) ix)-type CoAlgebraF s g r = CoAlgebraF' s (PF s) g r+type CoAlgebra' phi f r = forall ix. phi ix -> r -> f (K0 r) ix+type CoAlgebra phi r = CoAlgebra' phi (PF phi) r+type CoAlgebraF' phi f g r = forall ix. phi ix -> r -> g (f (K0 r) ix)+type CoAlgebraF phi g r = CoAlgebraF' phi (PF phi) g r -unfold :: (Ix s ix, HFunctor (PF s)) =>- CoAlgebra s r -> r -> ix-unfold f = to . hmap (\ _ (K0 x) -> I0 (unfold f x)) . f index+unfold :: (Fam phi, HFunctor phi (PF phi)) =>+ CoAlgebra phi r -> phi ix -> r -> ix+unfold f p = to p . hmap (\ p (K0 x) -> I0 (unfold f p x)) . f p -unfoldM :: (Ix s ix, HFunctor (PF s), Monad m) =>- CoAlgebraF s m r -> r -> m ix-unfoldM f x = f index x >>= liftMto . hmapM (\ _ (K0 x) -> liftM I0 (unfoldM f x))- where- -- only for ghc-6.8.3 compatibility- liftMto :: (Monad m, Ix s ix, pfs ~ PF s) => m (pfs s I0 ix) -> m ix- liftMto = liftM to+unfoldM :: (Fam phi, HFunctor phi (PF phi), Monad m) =>+ CoAlgebraF phi m r -> phi ix -> r -> m ix+unfoldM f p x = f p x >>= liftM (to p) . hmapM (\ p (K0 x) -> liftM I0 (unfoldM f p x)) -type ParaAlgebra' s f r = forall ix. Ix s ix => s ix -> f s (K0 r) ix -> ix -> r-type ParaAlgebra s r = ParaAlgebra' s (PF s) r-type ParaAlgebraF' s f g r = forall ix. Ix s ix => s ix -> f s (K0 r) ix -> ix -> g r-type ParaAlgebraF s g r = ParaAlgebraF' s (PF s) g r+type ParaAlgebra' phi f r = forall ix. phi ix -> f (K0 r) ix -> ix -> r+type ParaAlgebra phi r = ParaAlgebra' phi (PF phi) r+type ParaAlgebraF' phi f g r = forall ix. phi ix -> f (K0 r) ix -> ix -> g r+type ParaAlgebraF phi g r = ParaAlgebraF' phi (PF phi) g r -para :: (Ix s ix, HFunctor (PF s)) => - ParaAlgebra s r -> ix -> r-para f x = f index (hmap (\ _ (I0 x) -> K0 (para f x)) (from x)) x+para :: (Fam phi, HFunctor phi (PF phi)) => + ParaAlgebra phi r -> phi ix -> ix -> r+para f p x = f p (hmap (\ p (I0 x) -> K0 (para f p x)) (from p x)) x -paraM :: (Ix s ix, HFunctor (PF s), Monad m) => - ParaAlgebraF s m r -> ix -> m r-paraM f x = hmapM (\ _ (I0 x) -> liftM K0 (paraM f x)) (from x) >>= \ r -> f index r x+paraM :: (Fam phi, HFunctor phi (PF phi), Monad m) => + ParaAlgebraF phi m r -> phi ix -> ix -> m r+paraM f p x = hmapM (\ p (I0 x) -> liftM K0 (paraM f p x)) (from p x) >>= \ r -> f p r x -- * Creating an algebra infixr 5 & infixr :-> -type AlgPart a (s :: * -> *) b ix = a s (K0 b) ix -> b-type (f :-> g) (s :: * -> *) b ix = f s b ix -> g s b ix+type AlgPart f b ix = f (K0 b) ix -> b+type (f :-> g) b ix = f b ix -> g b ix -(&) :: (AlgPart a :-> AlgPart b :-> AlgPart (a :+: b)) s c ix+(&) :: (AlgPart a :-> AlgPart b :-> AlgPart (a :+: b)) c ix (f & g) (L x) = f x (f & g) (R x) = g x -tag :: AlgPart a s c ix -> AlgPart (a :>: ix) s c ix'+tag :: AlgPart a c ix -> AlgPart (a :>: ix) c ix' tag f (Tag x) = f x -con :: AlgPart a s b ix -> AlgPart (C c a) s b ix+con :: AlgPart a b ix -> AlgPart (C c a) b ix con f (C x) = f x
src/Generics/MultiRec/HFix.hs view
@@ -22,13 +22,14 @@ import Generics.MultiRec.Base import Generics.MultiRec.HFunctor+import Generics.MultiRec.Fold -- * Fixed point of indexed types data HFix (h :: (* -> *) -> * -> *) ix = HIn { hout :: h (HFix h) ix } -hfrom :: (pfs ~ PF s, Ix s ix, HFunctor (PF s)) => ix -> HFix (pfs s) ix-hfrom = HIn . hmap (const (hfrom . unI0)) . from+hfrom :: (Fam phi, HFunctor phi (PF phi)) => phi ix -> ix -> HFix (PF phi) ix+hfrom = fold (const HIn) -hto :: (pfs ~ PF s, Ix s ix, HFunctor (PF s)) => HFix (pfs s) ix -> ix-hto = to . hmap (const (I0 . hto)) . hout+hto :: (Fam phi, HFunctor phi (PF phi)) => phi ix -> HFix (PF phi) ix -> ix+hto = unfold (const hout)
src/Generics/MultiRec/HFunctor.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- |@@ -18,7 +20,7 @@ module Generics.MultiRec.HFunctor where import Control.Monad (liftM, liftM2)-import Control.Applicative (Applicative(..), liftA, liftA2, WrappedMonad(..))+import Control.Applicative (Applicative(..), (<$>), (<*>), WrappedMonad(..)) import Generics.MultiRec.Base @@ -27,46 +29,46 @@ -- We define a general 'hmapA' that works on applicative functors. -- The simpler 'hmap' is a special case. -class HFunctor f where+class HFunctor phi f where hmapA :: (Applicative a) =>- (forall ix. Ix s ix => s ix -> r ix -> a (r' ix)) ->- f s r ix -> a (f s r' ix)+ (forall ix. phi ix -> r ix -> a (r' ix)) ->+ f r ix -> a (f r' ix) -instance HFunctor (I xi) where- hmapA f (I x) = liftA I (f index x)+instance El phi xi => HFunctor phi (I xi) where+ hmapA f (I x) = I <$> f proof x -instance HFunctor (K x) where- hmapA _ (K x) = pure (K x)+instance HFunctor phi (K x) where+ hmapA _ (K x) = pure (K x) -instance HFunctor U where+instance HFunctor phi U where hmapA _ U = pure U -instance (HFunctor f, HFunctor g) => HFunctor (f :+: g) where- hmapA f (L x) = liftA L (hmapA f x)- hmapA f (R y) = liftA R (hmapA f y)+instance (HFunctor phi f, HFunctor phi g) => HFunctor phi (f :+: g) where+ hmapA f (L x) = L <$> hmapA f x+ hmapA f (R y) = R <$> hmapA f y -instance (HFunctor f, HFunctor g) => HFunctor (f :*: g) where- hmapA f (x :*: y) = liftA2 (:*:) (hmapA f x) (hmapA f y)+instance (HFunctor phi f, HFunctor phi g) => HFunctor phi (f :*: g) where+ hmapA f (x :*: y) = (:*:) <$> hmapA f x <*> hmapA f y -instance HFunctor f => HFunctor (f :>: ix) where- hmapA f (Tag x) = liftA Tag (hmapA f x)+instance HFunctor phi f => HFunctor phi (f :>: ix) where+ hmapA f (Tag x) = Tag <$> hmapA f x -instance HFunctor f => HFunctor (C c f) where- hmapA f (C x) = liftA C (hmapA f x)+instance (Constructor c, HFunctor phi f) => HFunctor phi (C c f) where+ hmapA f (C x) = C <$> hmapA f x -- | The function 'hmap' takes a functor @f@. All the recursive instances -- in that functor are wrapped by an application of @r@. The argument to -- 'hmap' takes a function that transformes @r@ occurrences into @r'@ -- occurrences, for every @ix@. In order to associate the index @ix@--- with the correct system @s@, the argument to @hmap@ is additionally--- parameterized by a witness of type @s ix@. -hmap :: (HFunctor f) =>- (forall ix. Ix s ix => s ix -> r ix -> r' ix) ->- f s r ix -> f s r' ix+-- with the correct family @phi@, the argument to @hmap@ is additionally+-- parameterized by a witness of type @phi ix@. +hmap :: (HFunctor phi f) =>+ (forall ix. phi ix -> r ix -> r' ix) ->+ f r ix -> f r' ix hmap f x = unI0 (hmapA (\ ix x -> I0 (f ix x)) x) -- | Monadic version of 'hmap'.-hmapM :: (HFunctor f, Monad m) =>- (forall ix. Ix s ix => s ix -> r ix -> m (r' ix)) ->- f s r ix -> m (f s r' ix)+hmapM :: (HFunctor phi f, Monad m) =>+ (forall ix. phi ix -> r ix -> m (r' ix)) ->+ f r ix -> m (f r' ix) hmapM f x = unwrapMonad (hmapA (\ ix x -> WrapMonad (f ix x)) x)
src/Generics/MultiRec/Show.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- |@@ -20,56 +22,51 @@ import Generics.MultiRec.Base import Generics.MultiRec.HFunctor-import Generics.MultiRec.Fold+import Generics.MultiRec.FoldK import qualified Prelude as P import Prelude hiding (show, showsPrec) -- * Generic show -class HFunctor f => HShow f where- hShowsPrecAlg :: Algebra' s f (K0 [Int -> ShowS])+class HFunctor phi f => HShow phi f where+ hShowsPrecAlg :: Algebra' phi f [Int -> ShowS] -instance HShow (I xi) where- hShowsPrecAlg _ (I (K0 x)) = K0 x+instance El phi xi => HShow phi (I xi) where+ hShowsPrecAlg _ (I (K0 x)) = x -- | For constant types, we make use of the standard -- show function.-instance Show x => HShow (K x) where- hShowsPrecAlg _ (K x) = K0 [\ n -> P.showsPrec n x]+instance Show a => HShow phi (K a) where+ hShowsPrecAlg _ (K x) = [\ n -> P.showsPrec n x] -instance HShow U where- hShowsPrecAlg _ U = K0 []+instance HShow phi U where+ hShowsPrecAlg _ U = [] -instance (HShow f, HShow g) => HShow (f :+: g) where+instance (HShow phi f, HShow phi g) => HShow phi (f :+: g) where hShowsPrecAlg ix (L x) = hShowsPrecAlg ix x hShowsPrecAlg ix (R y) = hShowsPrecAlg ix y -instance (HShow f, HShow g) => HShow (f :*: g) where- hShowsPrecAlg ix (x :*: y) = K0 (unK0 (hShowsPrecAlg ix x) ++ unK0 (hShowsPrecAlg ix y))+instance (HShow phi f, HShow phi g) => HShow phi (f :*: g) where+ hShowsPrecAlg ix (x :*: y) = hShowsPrecAlg ix x ++ hShowsPrecAlg ix y -instance HShow f => HShow (f :>: ix) where+instance HShow phi f => HShow phi (f :>: ix) where hShowsPrecAlg ix (Tag x) = hShowsPrecAlg ix x -instance HShow f => HShow (C c f) where+instance (Constructor c, HShow phi f) => HShow phi (C c f) where hShowsPrecAlg ix cx@(C x) = case conFixity cx of- Prefix -> K0 [\ n -> showParen (not (null fields) && n > 10)- (spaces ((conName cx ++) : map ($ 11) fields))]- Infix a p -> K0 [\ n -> showParen (n > p)- (spaces (head fields p : (conName cx ++) : map ($ p) (tail fields)))]+ Prefix -> [\ n -> showParen (not (null fields) && n > 10)+ (spaces ((conName cx ++) : map ($ 11) fields))]+ Infix a p -> [\ n -> showParen (n > p)+ (spaces (head fields p : (conName cx ++) : map ($ p) (tail fields)))] where- fields = unK0 $ hShowsPrecAlg ix x---- | A variant of the algebra that takes an extra argument--- to fix the system 's' the algebra works on.-hShowsPrecAlg_ :: (HShow f) => s ix -> Algebra' s f (K0 [Int -> ShowS])-hShowsPrecAlg_ _ = hShowsPrecAlg + fields = hShowsPrecAlg ix x -showsPrec :: forall s ix. (Ix s ix, HShow (PF s)) => s ix -> Int -> ix -> ShowS-showsPrec ix n x = spaces (map ($ n) (unK0 (fold (hShowsPrecAlg_ ix) x)))+showsPrec :: (Fam phi, HShow phi (PF phi)) => phi ix -> Int -> ix -> ShowS+showsPrec p n x = spaces (map ($ n) (fold hShowsPrecAlg p x)) -show :: forall s ix. (Ix s ix, HShow (PF s)) => s ix -> ix -> String+show :: (Fam phi, HShow phi (PF phi)) => phi ix -> ix -> String show ix x = showsPrec ix 0 x "" -- * Utilities
+ src/Generics/MultiRec/TEq.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE TypeOperators #-}++-----------------------------------------------------------------------------+-- |+-- Module : Generics.MultiRec.TEq+-- Copyright : (c) 2008--2009 Universiteit Utrecht+-- License : BSD3+--+-- Maintainer : generics@haskell.org+-- Stability : experimental+-- Portability : non-portable+--+-- Type-level equality. This module is currently provided by the multirec+-- library, even though it is more general and does not really belong here.+-- +-----------------------------------------------------------------------------+module Generics.MultiRec.TEq where++infix 4 :=:++data (:=:) :: * -> * -> * where+ Refl :: a :=: a++cast :: a :=: b -> a -> b+cast Refl x = x
src/Generics/MultiRec/TH.hs view
@@ -15,16 +15,18 @@ -- This module contains Template Haskell code that can be used to -- automatically generate the boilerplate code for the multiplate -- library. The constructor information can be generated per datatype,--- the rest per system of datatypes.+-- the rest per family of datatypes. -- ----------------------------------------------------------------------------- module Generics.MultiRec.TH ( deriveConstructors,- deriveSystem,+ deriveFamily, deriveSystem, derivePF,- deriveIx+ deriveEl,+ deriveFam,+ deriveEqS ) where import Generics.MultiRec.Base@@ -41,20 +43,27 @@ liftM concat . mapM constrInstance -- | Given the name of the index GADT, the names of the--- types in the system, and the name (as string) for the+-- types in the family, and the name (as string) for the -- pattern functor to derive, generate the 'Ix' and 'PF' -- instances. /IMPORTANT/: It is assumed that the constructors -- of the GADT have the same names as the datatypes in the -- family. -deriveSystem :: Name -> [Name] -> String -> Q [Dec]-deriveSystem n ns pfn =+deriveFamily :: Name -> [Name] -> String -> Q [Dec]+deriveFamily n ns pfn = do- pf <- derivePF pfn ns- ix <- deriveIx n ns- return $ pf ++ ix+ pf <- derivePF pfn ns+ el <- deriveEl n ns+ fam <- deriveFam n ns+ eq <- deriveEqS n (map (mkName . nameBase) ns)+ return $ pf ++ el ++ fam ++ eq --- | Derive only the 'PF' instance. Not needed if 'deriveSystem'+-- | Compatibility. Use deriveFamily instead.++deriveSystem :: Name -> [Name] -> String -> Q [Dec]+deriveSystem = deriveFamily++-- | Derive only the 'PF' instance. Not needed if 'deriveFamily' -- is used. derivePF :: String -> [Name] -> Q [Dec]@@ -65,13 +74,37 @@ sum :: Q Type -> Q Type -> Q Type sum a b = conT ''(:+:) `appT` a `appT` b --- | Derive only the 'Ix' instances. Not needed if 'deriveSystem'+-- | Derive only the 'El' instances. Not needed if 'deriveFamily' -- is used. -deriveIx :: Name -> [Name] -> Q [Dec]-deriveIx s ns =- zipWithM (ixInstance s ns (length ns)) [0..] ns+deriveEl :: Name -> [Name] -> Q [Dec]+deriveEl s ns =+ mapM (elInstance s) ns +-- | Dervie only the 'Fam' instance. Not needed if 'deriveFamily'+-- is used.++deriveFam :: Name -> [Name] -> Q [Dec]+deriveFam s ns =+ do+ fcs <- liftM concat $ zipWithM (mkFrom ns (length ns)) [0..] ns + tcs <- liftM concat $ zipWithM (mkTo ns (length ns)) [0..] ns+ liftM (:[]) $+ instanceD (cxt []) (conT ''Fam `appT` conT s)+ [funD 'from fcs, funD 'to tcs]++-- | Derive only the 'EqS' instance. Not needed if 'deriveFamily'+-- is used.++deriveEqS :: Name -> [Name] -> Q [Dec]+deriveEqS s ns =+ liftM (:[]) $+ instanceD (cxt []) (conT ''EqS `appT` conT s)+ [funD 'eqS (map trueClause ns ++ [falseClause])]+ where+ trueClause n = clause [conP n [], conP n []] (normalB (conE 'Just `appE` conE 'Refl)) []+ falseClause = clause [wildP, wildP] (normalB (conE 'Nothing)) []+ constrInstance :: Name -> Q [Dec] constrInstance n = do@@ -149,72 +182,74 @@ pfField ns t@(ConT n) | n `elem` ns = conT ''I `appT` return t pfField ns t = conT ''K `appT` return t -ixInstance :: Name -> [Name] -> Int -> Int -> Name -> Q Dec-ixInstance s ns m i n =- instanceD (cxt []) (conT ''Ix `appT` conT s `appT` conT n)- [mkFrom ns n m i, mkTo ns n m i, mkIndex n]+elInstance :: Name -> Name -> Q Dec+elInstance s n =+ instanceD (cxt []) (conT ''El `appT` conT s `appT` conT n)+ [mkProof n] -mkFrom :: [Name] -> Name -> Int -> Int -> Q Dec-mkFrom ns n m i =+mkFrom :: [Name] -> Int -> Int -> Name -> Q [Q Clause]+mkFrom ns m i n = do -- runIO $ putStrLn $ "processing " ++ show n let wrapE e = lrE m i (conE 'Tag `appE` e) i <- reify n+ let dn = mkName (nameBase n) let b = case i of TyConI (DataD _ _ _ cs _) ->- zipWith (fromCon wrapE ns (length cs)) [0..] cs+ zipWith (fromCon wrapE ns dn (length cs)) [0..] cs TyConI (TySynD t _ _) ->- [clause [varP (field 0)] (normalB (wrapE $ conE 'K `appE` varE (field 0))) []]- _ -> error "unknown construct" - funD 'from_ b + [clause [conP dn [], varP (field 0)] (normalB (wrapE $ conE 'K `appE` varE (field 0))) []]+ _ -> error "unknown construct"+ return b -mkTo :: [Name] -> Name -> Int -> Int -> Q Dec-mkTo ns n m i =+mkTo :: [Name] -> Int -> Int -> Name -> Q [Q Clause]+mkTo ns m i n = do -- runIO $ putStrLn $ "processing " ++ show n let wrapP p = lrP m i (conP 'Tag [p]) i <- reify n+ let dn = mkName (nameBase n) let b = case i of TyConI (DataD _ _ _ cs _) ->- zipWith (toCon wrapP ns (length cs)) [0..] cs+ zipWith (toCon wrapP ns dn (length cs)) [0..] cs TyConI (TySynD t _ _) ->- [clause [wrapP $ conP 'K [varP (field 0)]] (normalB $ varE (field 0)) []]+ [clause [conP dn [], wrapP $ conP 'K [varP (field 0)]] (normalB $ varE (field 0)) []] _ -> error "unknown construct" - funD 'to_ b + return b -mkIndex :: Name -> Q Dec-mkIndex n =- funD 'index [clause [] (normalB (conE (mkName (nameBase n)))) []]+mkProof :: Name -> Q Dec+mkProof n =+ funD 'proof [clause [] (normalB (conE (mkName (nameBase n)))) []] -fromCon :: (Q Exp -> Q Exp) -> [Name] -> Int -> Int -> Con -> Q Clause-fromCon wrap ns m i (NormalC n []) =+fromCon :: (Q Exp -> Q Exp) -> [Name] -> Name -> Int -> Int -> Con -> Q Clause+fromCon wrap ns n m i (NormalC cn []) = clause- [conP n []]+ [conP n [], conP cn []] (normalB $ wrap $ lrE m i $ conE 'C `appE` (conE 'U)) []-fromCon wrap ns m i (NormalC n fs) =+fromCon wrap ns n m i (NormalC cn fs) = -- runIO (putStrLn ("constructor " ++ show ix)) >> clause- [conP n (map (varP . field) [0..length fs - 1])]+ [conP n [], conP cn (map (varP . field) [0..length fs - 1])] (normalB $ wrap $ lrE m i $ conE 'C `appE` foldr1 prod (zipWith (fromField ns) [0..] (map snd fs))) [] where prod x y = conE '(:*:) `appE` x `appE` y-fromCon wrap ns m i (InfixC t1 n t2) =- fromCon wrap ns m i (NormalC n [t1,t2])+fromCon wrap ns n m i (InfixC t1 cn t2) =+ fromCon wrap ns n m i (NormalC cn [t1,t2]) -toCon :: (Q Pat -> Q Pat) -> [Name] -> Int -> Int -> Con -> Q Clause-toCon wrap ns m i (NormalC n []) =+toCon :: (Q Pat -> Q Pat) -> [Name] -> Name -> Int -> Int -> Con -> Q Clause+toCon wrap ns n m i (NormalC cn []) = clause- [wrap $ lrP m i $ conP 'C [conP 'U []]]- (normalB $ conE n) []-toCon wrap ns m i (NormalC n fs) =+ [conP n [], wrap $ lrP m i $ conP 'C [conP 'U []]]+ (normalB $ conE cn) []+toCon wrap ns n m i (NormalC cn fs) = -- runIO (putStrLn ("constructor " ++ show ix)) >> clause- [wrap $ lrP m i $ conP 'C [foldr1 prod (zipWith (toField ns) [0..] (map snd fs))]]- (normalB $ foldl appE (conE n) (map (varE . field) [0..length fs - 1])) []+ [conP n [], wrap $ lrP m i $ conP 'C [foldr1 prod (zipWith (toField ns) [0..] (map snd fs))]]+ (normalB $ foldl appE (conE cn) (map (varE . field) [0..length fs - 1])) [] where prod x y = conP '(:*:) [x,y]-toCon wrap ns m i (InfixC t1 n t2) =- toCon wrap ns m i (NormalC n [t1,t2])+toCon wrap ns n m i (InfixC t1 cn t2) =+ toCon wrap ns n m i (NormalC cn [t1,t2]) fromField :: [Name] -> Int -> Type -> Q Exp fromField ns nr t@(ConT n) | n `elem` ns = conE 'I `appE` (conE 'I0 `appE` varE (field nr))