deep-transformations 0.1 → 0.2
raw patch · 16 files changed
+415/−83 lines, 16 filesdep +transformersdep ~basedep ~generic-lensdep ~template-haskellPVP ok
version bump matches the API change (PVP)
Dependencies added: transformers
Dependency ranges changed: base, generic-lens, template-haskell
API changes (from Hackage documentation)
- Transformation.AG: fullMapDefault :: (p ~ Domain t, q ~ Semantics t, q ~ Codomain t, x ~ g q q, Apply (g q), Functor t g, Attribution t g p p) => (forall a. p a -> a) -> t -> p (g p p) -> q (g q q)
- Transformation.AG.Generics: instance (Transformation.Transformation t, Transformation.Domain t GHC.Types.~ (,) a) => Transformation.AG.Generics.Revelation t ((,) a)
- Transformation.AG.Generics: instance (Transformation.Transformation t, Transformation.Domain t GHC.Types.~ Data.Functor.Identity.Identity) => Transformation.AG.Generics.Revelation t Data.Functor.Identity.Identity
- Transformation.AG.Generics: instance (sem GHC.Types.~ Transformation.AG.Semantics t, Transformation.Domain t GHC.Types.~ shallow, Transformation.AG.Generics.Revelation t shallow, Transformation.Shallow.Functor (Transformation.AG.Generics.PassDown t sem (Transformation.AG.Atts (Transformation.AG.Inherited t) (g sem sem))) (g sem)) => Transformation.AG.Generics.Bequether t g (Transformation.AG.Semantics t) shallow
- Transformation.Deep: instance Rank2.Functor (Transformation.Deep.Product g1 g2 p)
+ Transformation.AG: AllAtts :: Atts (Inherited t) a -> Atts (Synthesized t) a -> AllAtts t a
+ Transformation.AG: [allInh] :: AllAtts t a -> Atts (Inherited t) a
+ Transformation.AG: [allSyn] :: AllAtts t a -> Atts (Synthesized t) a
+ Transformation.AG: applyDefaultWithAttributes :: (p ~ Domain t, q ~ PreservingSemantics t p, x ~ g q q, Apply (g q), Atts (Inherited t) (g q q) ~ Atts (Inherited t) (g (Semantics t) (Semantics t)), Atts (Synthesized t) (g q q) ~ Atts (Synthesized t) (g (Semantics t) (Semantics t)), g q (Synthesized t) ~ g (Semantics t) (Synthesized t), g q (Inherited t) ~ g (Semantics t) (Inherited t), Attribution t g (PreservingSemantics t p) p) => (forall a. p a -> a) -> t -> p (g (PreservingSemantics t p) (PreservingSemantics t p)) -> PreservingSemantics t p (g (PreservingSemantics t p) (PreservingSemantics t p))
+ Transformation.AG: data AllAtts t a
+ Transformation.AG: knitKeeping :: forall t f g sem. (sem ~ PreservingSemantics t f, Apply (g sem), Atts (Inherited t) (g sem sem) ~ Atts (Inherited t) (g (Semantics t) (Semantics t)), Atts (Synthesized t) (g sem sem) ~ Atts (Synthesized t) (g (Semantics t) (Semantics t)), g sem (Synthesized t) ~ g (Semantics t) (Synthesized t), g sem (Inherited t) ~ g (Semantics t) (Inherited t)) => (forall a. f a -> a) -> Rule t g -> f (g (PreservingSemantics t f) (PreservingSemantics t f)) -> PreservingSemantics t f (g (PreservingSemantics t f) (PreservingSemantics t f))
+ Transformation.AG: type PreservingSemantics t f = Arrow (Inherited t) (Product (AllAtts t) f)
+ Transformation.AG.Generics: Keep :: t -> Keep t
+ Transformation.AG.Generics: instance (Transformation.AG.Generics.Revelation (Transformation.AG.Generics.Auto t), Transformation.Domain (Transformation.AG.Generics.Auto t) GHC.Types.~ f, Transformation.Codomain (Transformation.AG.Generics.Auto t) GHC.Types.~ Transformation.AG.Semantics (Transformation.AG.Generics.Auto t), Rank2.Apply (g (Transformation.AG.Semantics (Transformation.AG.Generics.Auto t))), Transformation.AG.Attribution (Transformation.AG.Generics.Auto t) g (Transformation.AG.Semantics (Transformation.AG.Generics.Auto t)) f) => Transformation.At (Transformation.AG.Generics.Auto t) (g (Transformation.AG.Semantics (Transformation.AG.Generics.Auto t)) (Transformation.AG.Semantics (Transformation.AG.Generics.Auto t)))
+ Transformation.AG.Generics: instance (Transformation.AG.Generics.Revelation (Transformation.AG.Generics.Keep t), p GHC.Types.~ Transformation.Domain (Transformation.AG.Generics.Keep t), Rank2.Apply (g q), q GHC.Types.~ Transformation.Codomain (Transformation.AG.Generics.Keep t), q GHC.Types.~ Transformation.AG.PreservingSemantics (Transformation.AG.Generics.Keep t) p, s GHC.Types.~ Transformation.AG.Semantics (Transformation.AG.Generics.Keep t), Transformation.AG.Atts (Transformation.AG.Inherited (Transformation.AG.Generics.Keep t)) (g q q) GHC.Types.~ Transformation.AG.Atts (Transformation.AG.Inherited (Transformation.AG.Generics.Keep t)) (g s s), Transformation.AG.Atts (Transformation.AG.Synthesized (Transformation.AG.Generics.Keep t)) (g q q) GHC.Types.~ Transformation.AG.Atts (Transformation.AG.Synthesized (Transformation.AG.Generics.Keep t)) (g s s), g q (Transformation.AG.Synthesized (Transformation.AG.Generics.Keep t)) GHC.Types.~ g s (Transformation.AG.Synthesized (Transformation.AG.Generics.Keep t)), g q (Transformation.AG.Inherited (Transformation.AG.Generics.Keep t)) GHC.Types.~ g s (Transformation.AG.Inherited (Transformation.AG.Generics.Keep t)), Transformation.AG.Attribution (Transformation.AG.Generics.Keep t) g q p) => Transformation.At (Transformation.AG.Generics.Keep t) (g (Transformation.AG.PreservingSemantics (Transformation.AG.Generics.Keep t) p) (Transformation.AG.PreservingSemantics (Transformation.AG.Generics.Keep t) p))
+ Transformation.AG.Generics: instance (Transformation.Transformation (Transformation.AG.Generics.Auto t), Transformation.Domain (Transformation.AG.Generics.Auto t) GHC.Types.~ f, GHC.Base.Functor f, Transformation.Codomain (Transformation.AG.Generics.Auto t) GHC.Types.~ Transformation.AG.Semantics (Transformation.AG.Generics.Auto t), Transformation.Deep.Functor (Transformation.AG.Generics.Auto t) g, Transformation.At (Transformation.AG.Generics.Auto t) (g (Transformation.AG.Semantics (Transformation.AG.Generics.Auto t)) (Transformation.AG.Semantics (Transformation.AG.Generics.Auto t)))) => Transformation.Full.Functor (Transformation.AG.Generics.Auto t) g
+ Transformation.AG.Generics: instance (Transformation.Transformation (Transformation.AG.Generics.Keep t), Transformation.Domain (Transformation.AG.Generics.Keep t) GHC.Types.~ f, GHC.Base.Functor f, Transformation.Codomain (Transformation.AG.Generics.Keep t) GHC.Types.~ Transformation.AG.PreservingSemantics (Transformation.AG.Generics.Keep t) f, GHC.Base.Functor f, Transformation.Deep.Functor (Transformation.AG.Generics.Keep t) g, Transformation.At (Transformation.AG.Generics.Keep t) (g (Transformation.AG.PreservingSemantics (Transformation.AG.Generics.Keep t) f) (Transformation.AG.PreservingSemantics (Transformation.AG.Generics.Keep t) f))) => Transformation.Full.Functor (Transformation.AG.Generics.Keep t) g
+ Transformation.AG.Generics: instance (sem GHC.Types.~ Transformation.AG.Semantics t, Transformation.Domain t GHC.Types.~ shallow, Transformation.AG.Generics.Revelation t, Transformation.Shallow.Functor (Transformation.AG.Generics.PassDown t sem (Transformation.AG.Atts (Transformation.AG.Inherited t) (g sem sem))) (g sem)) => Transformation.AG.Generics.Bequether t g (Transformation.AG.Semantics t) shallow
+ Transformation.AG.Generics: newtype Keep t
+ Transformation.AG.Monomorphic: Atts :: a -> a -> Atts a
+ Transformation.AG.Monomorphic: Auto :: t -> Auto t
+ Transformation.AG.Monomorphic: Feeder :: Feeder a (f :: Type -> Type)
+ Transformation.AG.Monomorphic: Keep :: t -> Keep t
+ Transformation.AG.Monomorphic: [inh] :: Atts a -> a
+ Transformation.AG.Monomorphic: [syn] :: Atts a -> a
+ Transformation.AG.Monomorphic: applyDefault :: (p ~ Domain t, q ~ Semantics a, x ~ g q q, Foldable (g q), Attribution t a g q p, Monoid a) => (forall y. p y -> y) -> t -> p x -> q x
+ Transformation.AG.Monomorphic: applyDefaultWithAttributes :: (p ~ Domain t, q ~ PreservingSemantics p a, x ~ g q q, Attribution t a g q p, Foldable (g q), Monoid a, Foldable p, Functor p) => t -> p x -> q x
+ Transformation.AG.Monomorphic: attribution :: Attribution t a g deep shallow => t -> shallow (g deep deep) -> Rule a
+ Transformation.AG.Monomorphic: class Attribution t a g (deep :: Type -> Type) shallow
+ Transformation.AG.Monomorphic: data Atts a
+ Transformation.AG.Monomorphic: data Feeder a (f :: Type -> Type)
+ Transformation.AG.Monomorphic: fullMapDefault :: (p ~ Domain t, q ~ Semantics a, q ~ Codomain t, x ~ g q q, Foldable (g q), Functor t g, Attribution t a g p p, Monoid a) => (forall y. p y -> y) -> t -> p (g p p) -> q (g q q)
+ Transformation.AG.Monomorphic: instance (Data.Traversable.Traversable f, Transformation.Deep.Traversable (Transformation.AG.Monomorphic.Feeder a f) g) => Transformation.Full.Traversable (Transformation.AG.Monomorphic.Feeder a f) g
+ Transformation.AG.Monomorphic: instance (Transformation.Transformation (Transformation.AG.Monomorphic.Auto t), Transformation.Domain (Transformation.AG.Monomorphic.Auto t) GHC.Types.~ f, GHC.Base.Functor f, Transformation.Codomain (Transformation.AG.Monomorphic.Auto t) GHC.Types.~ Transformation.AG.Monomorphic.Semantics (Transformation.AG.Monomorphic.Auto t), Transformation.Deep.Functor (Transformation.AG.Monomorphic.Auto t) g, Transformation.At (Transformation.AG.Monomorphic.Auto t) (g (Transformation.AG.Monomorphic.Semantics (Transformation.AG.Monomorphic.Auto t)) (Transformation.AG.Monomorphic.Semantics (Transformation.AG.Monomorphic.Auto t)))) => Transformation.Full.Functor (Transformation.AG.Monomorphic.Auto t) g
+ Transformation.AG.Monomorphic: instance (Transformation.Transformation (Transformation.AG.Monomorphic.Auto t), p GHC.Types.~ Transformation.Domain (Transformation.AG.Monomorphic.Auto t), q GHC.Types.~ Transformation.Codomain (Transformation.AG.Monomorphic.Auto t), q GHC.Types.~ Transformation.AG.Monomorphic.Semantics a, Rank2.Foldable (g q), GHC.Base.Monoid a, Data.Foldable.Foldable p, Transformation.AG.Monomorphic.Attribution (Transformation.AG.Monomorphic.Auto t) a g q p) => Transformation.At (Transformation.AG.Monomorphic.Auto t) (g (Transformation.AG.Monomorphic.Semantics a) (Transformation.AG.Monomorphic.Semantics a))
+ Transformation.AG.Monomorphic: instance (Transformation.Transformation (Transformation.AG.Monomorphic.Keep t), Transformation.Domain (Transformation.AG.Monomorphic.Keep t) GHC.Types.~ f, Data.Traversable.Traversable f, Rank2.Traversable (g f), Transformation.Codomain (Transformation.AG.Monomorphic.Keep t) GHC.Types.~ Transformation.AG.Monomorphic.PreservingSemantics f a, Transformation.Deep.Traversable (Transformation.AG.Monomorphic.Feeder a f) g, Transformation.Full.Functor (Transformation.AG.Monomorphic.Keep t) g, Transformation.At (Transformation.AG.Monomorphic.Keep t) (g (Transformation.AG.Monomorphic.PreservingSemantics f a) (Transformation.AG.Monomorphic.PreservingSemantics f a))) => Transformation.Full.Traversable (Transformation.AG.Monomorphic.Keep t) g
+ Transformation.AG.Monomorphic: instance (Transformation.Transformation (Transformation.AG.Monomorphic.Keep t), Transformation.Domain (Transformation.AG.Monomorphic.Keep t) GHC.Types.~ f, GHC.Base.Functor f, Transformation.Codomain (Transformation.AG.Monomorphic.Keep t) GHC.Types.~ Transformation.AG.Monomorphic.PreservingSemantics f a, GHC.Base.Functor f, Transformation.Deep.Functor (Transformation.AG.Monomorphic.Keep t) g, Transformation.At (Transformation.AG.Monomorphic.Keep t) (g (Transformation.AG.Monomorphic.PreservingSemantics f a) (Transformation.AG.Monomorphic.PreservingSemantics f a))) => Transformation.Full.Functor (Transformation.AG.Monomorphic.Keep t) g
+ Transformation.AG.Monomorphic: instance (Transformation.Transformation (Transformation.AG.Monomorphic.Keep t), p GHC.Types.~ Transformation.Domain (Transformation.AG.Monomorphic.Keep t), q GHC.Types.~ Transformation.Codomain (Transformation.AG.Monomorphic.Keep t), q GHC.Types.~ Transformation.AG.Monomorphic.PreservingSemantics p a, Rank2.Foldable (g q), GHC.Base.Monoid a, Data.Foldable.Foldable p, GHC.Base.Functor p, Transformation.AG.Monomorphic.Attribution (Transformation.AG.Monomorphic.Keep t) a g q p) => Transformation.At (Transformation.AG.Monomorphic.Keep t) (g (Transformation.AG.Monomorphic.PreservingSemantics p a) (Transformation.AG.Monomorphic.PreservingSemantics p a))
+ Transformation.AG.Monomorphic: instance Data.Data.Data a => Data.Data.Data (Transformation.AG.Monomorphic.Atts a)
+ Transformation.AG.Monomorphic: instance GHC.Base.Monoid a => GHC.Base.Monoid (Transformation.AG.Monomorphic.Atts a)
+ Transformation.AG.Monomorphic: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Transformation.AG.Monomorphic.Atts a)
+ Transformation.AG.Monomorphic: instance GHC.Show.Show a => GHC.Show.Show (Transformation.AG.Monomorphic.Atts a)
+ Transformation.AG.Monomorphic: instance Transformation.AG.Monomorphic.Attribution t a g deep shallow
+ Transformation.AG.Monomorphic: instance Transformation.At (Transformation.AG.Monomorphic.Feeder a f) g
+ Transformation.AG.Monomorphic: instance Transformation.Transformation (Transformation.AG.Monomorphic.Feeder a f)
+ Transformation.AG.Monomorphic: knit :: (Foldable (g sem), sem ~ Semantics a, Monoid a) => Rule a -> g sem sem -> sem (g sem sem)
+ Transformation.AG.Monomorphic: knitKeeping :: forall a f g sem. (Foldable (g sem), sem ~ PreservingSemantics f a, Monoid a, Foldable f, Functor f) => Rule a -> f (g sem sem) -> sem (g sem sem)
+ Transformation.AG.Monomorphic: newtype Auto t
+ Transformation.AG.Monomorphic: newtype Keep t
+ Transformation.AG.Monomorphic: traverseDefaultWithAttributes :: forall t p q r a g. (Transformation t, Domain t ~ p, Codomain t ~ Compose ((->) a) q, q ~ Compose ((,) (Atts a)) p, r ~ Compose ((->) a) q, Traversable p, Functor t g, Traversable (Feeder a p) g, At t (g r r)) => t -> p (g p p) -> a -> q (g q q)
+ Transformation.AG.Monomorphic: type PreservingSemantics f a = Compose ((->) a) (Compose ((,) (Atts a)) f)
+ Transformation.AG.Monomorphic: type Rule a = Atts a -> Atts a
+ Transformation.AG.Monomorphic: type Semantics a = Const (a -> a)
+ Transformation.Deep: InL :: s (g d d) -> Sum g h (d :: * -> *) (s :: * -> *)
+ Transformation.Deep: InR :: s (h d d) -> Sum g h (d :: * -> *) (s :: * -> *)
+ Transformation.Deep: data Sum g h (d :: * -> *) (s :: * -> *)
+ Transformation.Deep: eitherFromSum :: Sum g h d s -> Either (s (g d d)) (s (h d d))
+ Transformation.Deep: infixl 4 <$>
+ Transformation.Deep: instance (Data.Typeable.Internal.Typeable p, Data.Typeable.Internal.Typeable q, Data.Typeable.Internal.Typeable g1, Data.Typeable.Internal.Typeable g2, Data.Data.Data (q (g1 p p)), Data.Data.Data (q (g2 p p))) => Data.Data.Data (Transformation.Deep.Sum g1 g2 p q)
+ Transformation.Deep: instance (GHC.Show.Show (q (g1 p p)), GHC.Show.Show (q (g2 p p))) => GHC.Show.Show (Transformation.Deep.Sum g1 g2 p q)
+ Transformation.Deep: instance (Transformation.Full.Foldable t g, Transformation.Full.Foldable t h, Transformation.Codomain t GHC.Types.~ Data.Functor.Const.Const m) => Transformation.Deep.Foldable t (Transformation.Deep.Sum g h)
+ Transformation.Deep: instance (Transformation.Full.Functor t g, Transformation.Full.Functor t h) => Transformation.Deep.Functor t (Transformation.Deep.Sum g h)
+ Transformation.Deep: instance (Transformation.Full.Traversable t g, Transformation.Full.Traversable t h, Transformation.Codomain t GHC.Types.~ Data.Functor.Compose.Compose m f, GHC.Base.Applicative m) => Transformation.Deep.Traversable t (Transformation.Deep.Sum g h)
+ Transformation.Deep: instance Rank2.Foldable (Transformation.Deep.Sum g h p)
+ Transformation.Deep: instance Rank2.Functor (Transformation.Deep.Product g h p)
+ Transformation.Deep: instance Rank2.Functor (Transformation.Deep.Sum g h p)
+ Transformation.Deep: instance Rank2.Traversable (Transformation.Deep.Sum g h p)
+ Transformation.Full: infixl 4 <$>
+ Transformation.Rank2: infixl 4 <$>
+ Transformation.Shallow: infixl 4 <$>
- Transformation.AG: type Rule t g = forall sem. sem ~ Semantics t => (Inherited t (g sem sem), g sem (Synthesized t)) -> (Synthesized t (g sem sem), g sem (Inherited t))
+ Transformation.AG: type Rule t g = forall sem. sem ~ Semantics t => (Inherited t (g sem (Semantics t)), g sem (Synthesized t)) -> (Synthesized t (g sem (Semantics t)), g sem (Inherited t))
- Transformation.AG.Generics: bequestDefault :: forall t g shallow sem. (sem ~ Semantics t, Domain t ~ shallow, Revelation t shallow, Functor (PassDown t sem (Atts (Inherited t) (g sem sem))) (g sem)) => t -> shallow (g sem sem) -> Atts (Inherited t) (g sem sem) -> g sem (Synthesized t) -> g sem (Inherited t)
+ Transformation.AG.Generics: bequestDefault :: forall t g shallow sem. (sem ~ Semantics t, Domain t ~ shallow, Revelation t, Functor (PassDown t sem (Atts (Inherited t) (g sem sem))) (g sem)) => t -> shallow (g sem sem) -> Atts (Inherited t) (g sem sem) -> g sem (Synthesized t) -> g sem (Inherited t)
- Transformation.AG.Generics: class (Transformation t, dom ~ Domain t) => Revelation t dom
+ Transformation.AG.Generics: class Transformation t => Revelation t
- Transformation.AG.Generics: reveal :: Revelation t dom => t -> dom x -> x
+ Transformation.AG.Generics: reveal :: Revelation t => t -> Domain t x -> x
- Transformation.Deep: Pair :: q (g1 p p) -> q (g2 p p) -> Product g1 g2 (p :: * -> *) (q :: * -> *)
+ Transformation.Deep: Pair :: s (g d d) -> s (h d d) -> Product g h (d :: * -> *) (s :: * -> *)
- Transformation.Deep: [fst] :: Product g1 g2 (p :: * -> *) (q :: * -> *) -> q (g1 p p)
+ Transformation.Deep: [fst] :: Product g h (d :: * -> *) (s :: * -> *) -> s (g d d)
- Transformation.Deep: [snd] :: Product g1 g2 (p :: * -> *) (q :: * -> *) -> q (g2 p p)
+ Transformation.Deep: [snd] :: Product g h (d :: * -> *) (s :: * -> *) -> s (h d d)
- Transformation.Deep: data Product g1 g2 (p :: * -> *) (q :: * -> *)
+ Transformation.Deep: data Product g h (d :: * -> *) (s :: * -> *)
Files
- CHANGELOG.md +24/−0
- README.md +16/−9
- deep-transformations.cabal +8/−5
- src/Transformation.hs +1/−1
- src/Transformation/AG.hs +47/−11
- src/Transformation/AG/Generics.hs +52/−14
- src/Transformation/AG/Monomorphic.hs +153/−0
- src/Transformation/Deep.hs +43/−3
- src/Transformation/Deep/TH.hs +9/−2
- src/Transformation/Full.hs +3/−2
- src/Transformation/Rank2.hs +1/−0
- src/Transformation/Shallow.hs +2/−1
- src/Transformation/Shallow/TH.hs +14/−1
- test/README.lhs +16/−9
- test/RepMin.hs +16/−9
- test/RepMinAuto.hs +10/−16
+ CHANGELOG.md view
@@ -0,0 +1,24 @@+# Revision history for deep-transformations++## 0.2 -- 2022-03-27++* Changes necessary to compile with GHC 9.2.2+* Excluded GHC 8.2.2 from `deep-transformations` and GitHub CI+* Increased the `deep-transformations`' bottom bound of base dependency+* Fixed `deep-transformations` compilation with GHC 9.0.1+* Added an explicit implementation `mappend = (<>)`+* Used haskell-ci to generate GitHub CI+* Incremented upper dependency bounds+* Added `AG.Generics.Keep`+* Added `knitKeeping` and `applyDefaultWithAttributes` to `AG`+* Dropped `fullMapDefault`+* Switch the README's attribute grammar functor to map upwards+* Removed unused code+* Added `infixl 4` declarations for all `<$>` methods+* Added the `AG.Monomorphic` module+* Fixed `Transformation.Shallow.TH` for repeated type parameters+* Added `Transformation.Deep.Sum`++## 0.1 -- 2020-11-11++First version
README.md view
@@ -31,6 +31,7 @@ import Data.Coerce (coerce) import Data.Functor.Const import Data.Functor.Identity+import Data.Monoid import qualified Rank2 import Transformation (Transformation, At) import qualified Transformation@@ -279,11 +280,17 @@ type Domain DeadCodeEliminator = Identity type Codomain DeadCodeEliminator = AG.Semantics DeadCodeEliminator +instance DeadCodeEliminator `Transformation.At` Decl Sem Sem where+ ($) = AG.applyDefault runIdentity++instance DeadCodeEliminator `Transformation.At` Expr Sem Sem where+ ($) = AG.applyDefault runIdentity+ instance Full.Functor DeadCodeEliminator Decl where- (<$>) = AG.fullMapDefault runIdentity+ (<$>) = Full.mapUpDefault instance Full.Functor DeadCodeEliminator Expr where- (<$>) = AG.fullMapDefault runIdentity+ (<$>) = Full.mapUpDefault ~~~ We also need another bit of a boilerplate instance that can be automatically generated with Template Haskell functions@@ -359,11 +366,11 @@ because they don't have any children. ~~~ {.haskell}-instance AG.Attribution DeadCodeEliminator Expr Identity Identity where- attribution DeadCodeEliminator (Identity e@(EVar v)) (AG.Inherited env, _) =- (AG.Synthesized (maybe e id $ env v), EVar v)- attribution DeadCodeEliminator (Identity e@(Con n)) (AG.Inherited env, _) =- (AG.Synthesized e, Con n)+instance AG.Attribution DeadCodeEliminator Expr Sem Identity where+ attribution DeadCodeEliminator (Identity (EVar v)) (AG.Inherited env, _) =+ (AG.Synthesized (maybe (EVar v) id $ env v), EVar v)+ attribution DeadCodeEliminator (Identity (Con n)) (AG.Inherited env, _) =+ (AG.Synthesized (Con n), Con n) ~~~ The `Add` and `Mul` nodes' rules need only to pass their inheritance down and to re-join the synthesized child@@ -388,7 +395,7 @@ attribution DeadCodeEliminator (Identity (Let _decl expr)) (AG.Inherited env, (Let (AG.Synthesized ~(env', decl')) (AG.Synthesized expr'))) = (AG.Synthesized (maybe id (bin Let) decl' expr'),- Let (AG.Inherited (env, Full.foldMap GetVariables expr)) (AG.Inherited $ \v-> env' v <|> env v))+ Let (AG.Inherited (env, Deep.foldMap GetVariables expr')) (AG.Inherited $ \v-> env' v <|> env v)) ~~~ ### Declaration rules@@ -396,7 +403,7 @@ The rules for `Decl` are a bit more involved. ~~~ {.haskell}-instance AG.Attribution DeadCodeEliminator Decl Identity Identity where+instance AG.Attribution DeadCodeEliminator Decl Sem Identity where ~~~ A single variable binding can be in three distinct situations. If the variable is not referenced at all, we can just
deep-transformations.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: deep-transformations-version: 0.1+version: 0.2 synopsis: Deep natural and unnatural tree transformations, including attribute grammars description: @@ -22,7 +22,8 @@ category: Control, Generics build-type: Custom cabal-version: >=1.10-extra-source-files: README.md+tested-with: GHC==9.0.1, GHC==8.10.4, GHC==8.8.4, GHC==8.6.5, GHC==8.4.4+extra-source-files: README.md, CHANGELOG.md source-repository head type: git location: https://github.com/blamario/grampa@@ -38,10 +39,12 @@ Transformation.Shallow, Transformation.Shallow.TH, Transformation.Deep, Transformation.Deep.TH, Transformation.Full, Transformation.Full.TH,- Transformation.Rank2, Transformation.AG, Transformation.AG.Generics+ Transformation.Rank2,+ Transformation.AG, Transformation.AG.Monomorphic, Transformation.AG.Generics ghc-options: -Wall- build-depends: base >= 4.7 && < 5, rank2classes >= 1.4.1 && < 1.5,- template-haskell >= 2.11 && < 2.17, generic-lens == 2.0.*+ build-depends: base >= 4.11 && < 5, rank2classes >= 1.4.1 && < 1.5,+ transformers >= 0.5 && < 0.7,+ template-haskell >= 2.11 && < 2.19, generic-lens >= 1.2 && < 2.3 default-language: Haskell2010 test-suite doctests
src/Transformation.hs view
@@ -56,7 +56,7 @@ instance (t `At` x, u `At` x, Domain t ~ Codomain u) => Compose t u `At` x where Compose t u $ x = t $ (u $ x) -instance Transformation (Rank2.Arrow p q x) where+instance Transformation (Rank2.Arrow (p :: Type -> Type) q x) where type Domain (Rank2.Arrow p q x) = p type Codomain (Rank2.Arrow p q x) = q
src/Transformation/AG.hs view
@@ -1,5 +1,5 @@ {-# Language FlexibleContexts, FlexibleInstances,- MultiParamTypeClasses, RankNTypes, StandaloneDeriving,+ MultiParamTypeClasses, RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeFamilies, TypeOperators, UndecidableInstances #-} -- | An attribute grammar is a particular kind of 'Transformation' that assigns attributes to nodes in a@@ -8,9 +8,10 @@ module Transformation.AG where +import Unsafe.Coerce (unsafeCoerce)+ import qualified Rank2-import Transformation (Domain, Codomain)-import qualified Transformation.Deep as Deep+import qualified Transformation -- | Type family that maps a node type to the type of its attributes, indexed per type constructor. type family Atts (f :: * -> *) a@@ -27,11 +28,19 @@ -- attributes. type Semantics t = Inherited t Rank2.~> Synthesized t +-- | A node's 'PreservingSemantics' is a natural tranformation from the node's inherited attributes to all its+-- attributes paired with the preserved node.+type PreservingSemantics t f = Rank2.Arrow (Inherited t) (Rank2.Product (AllAtts t) f)++-- | All inherited and synthesized attributes+data AllAtts t a = AllAtts{allInh :: Atts (Inherited t) a,+ allSyn :: Atts (Synthesized t) a}+ -- | An attribution rule maps a node's inherited attributes and its child nodes' synthesized attributes to the node's -- synthesized attributes and the children nodes' inherited attributes. type Rule t g = forall sem . sem ~ Semantics t- => (Inherited t (g sem sem), g sem (Synthesized t))- -> (Synthesized t (g sem sem), g sem (Inherited t))+ => (Inherited t (g sem (Semantics t)), g sem (Synthesized t))+ -> (Synthesized t (g sem (Semantics t)), g sem (Inherited t)) -- | The core function to tie the recursive knot, turning a 'Rule' for a node into its 'Semantics'. knit :: (Rank2.Apply (g sem), sem ~ Semantics t) => Rule t g -> g sem sem -> sem (g sem sem)@@ -40,6 +49,28 @@ where (synthesized, chInh) = r (inherited, chSyn) chSyn = chSem Rank2.<*> chInh +-- | Another way to tie the recursive knot, using a 'Rule' to add 'AllAtts' information to every node+knitKeeping :: forall t f g sem. (sem ~ PreservingSemantics t f, Rank2.Apply (g sem),+ Atts (Inherited t) (g sem sem) ~ Atts (Inherited t) (g (Semantics t) (Semantics t)),+ Atts (Synthesized t) (g sem sem) ~ Atts (Synthesized t) (g (Semantics t) (Semantics t)),+ g sem (Synthesized t) ~ g (Semantics t) (Synthesized t),+ g sem (Inherited t) ~ g (Semantics t) (Inherited t))+ => (forall a. f a -> a) -> Rule t g -> f (g (PreservingSemantics t f) (PreservingSemantics t f))+ -> PreservingSemantics t f (g (PreservingSemantics t f) (PreservingSemantics t f))+knitKeeping extract rule x = Rank2.Arrow knitted+ where knitted :: Inherited t (g (PreservingSemantics t f) (PreservingSemantics t f))+ -> Rank2.Product (AllAtts t) f (g (PreservingSemantics t f) (PreservingSemantics t f))+ chSem :: g (PreservingSemantics t f) (PreservingSemantics t f)+ knitted inherited = Rank2.Pair AllAtts{allInh= inh inherited, allSyn= syn synthesized} x+ where chInh :: g (PreservingSemantics t f) (Inherited t)+ chSyn :: g (PreservingSemantics t f) (Synthesized t)+ chKept :: g (PreservingSemantics t f) (Rank2.Product (AllAtts t) f)+ synthesized :: Synthesized t (g (PreservingSemantics t f) (PreservingSemantics t f))+ (synthesized, chInh) = unsafeCoerce (rule (unsafeCoerce inherited, unsafeCoerce chSyn))+ chSyn = Synthesized . allSyn . Rank2.fst Rank2.<$> chKept+ chKept = chSem Rank2.<*> chInh+ chSem = extract x+ -- | The core type class for defining the attribute grammar. The instances of this class typically have a form like -- -- > instance Attribution MyAttGrammar MyNode (Semantics MyAttGrammar) Identity where@@ -63,9 +94,14 @@ applyDefault extract t x = knit (attribution t x) (extract x) {-# INLINE applyDefault #-} --- | Drop-in implementation of 'Transformation.Full.<$>'-fullMapDefault :: (p ~ Domain t, q ~ Semantics t, q ~ Codomain t, x ~ g q q, Rank2.Apply (g q),- Deep.Functor t g, Attribution t g p p)- => (forall a. p a -> a) -> t -> p (g p p) -> q (g q q)-fullMapDefault extract t local = knit (attribution t local) (t Deep.<$> extract local)-{-# INLINE fullMapDefault #-}+-- | Drop-in implementation of 'Transformation.$' that preserves all attributes with every original node+applyDefaultWithAttributes :: (p ~ Transformation.Domain t, q ~ PreservingSemantics t p, x ~ g q q, Rank2.Apply (g q),+ Atts (Inherited t) (g q q) ~ Atts (Inherited t) (g (Semantics t) (Semantics t)),+ Atts (Synthesized t) (g q q) ~ Atts (Synthesized t) (g (Semantics t) (Semantics t)),+ g q (Synthesized t) ~ g (Semantics t) (Synthesized t),+ g q (Inherited t) ~ g (Semantics t) (Inherited t),+ Attribution t g (PreservingSemantics t p) p)+ => (forall a. p a -> a) -> t -> p (g (PreservingSemantics t p) (PreservingSemantics t p))+ -> PreservingSemantics t p (g (PreservingSemantics t p) (PreservingSemantics t p))+applyDefaultWithAttributes extract t x = knitKeeping extract (attribution t x) x+{-# INLINE applyDefaultWithAttributes #-}
src/Transformation/AG/Generics.hs view
@@ -1,5 +1,5 @@ {-# Language DataKinds, DefaultSignatures, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving,- MultiParamTypeClasses, PolyKinds, RankNTypes, ScopedTypeVariables, StandaloneDeriving,+ InstanceSigs, MultiParamTypeClasses, PolyKinds, RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-} -- | This module can be used to scrap the boilerplate attribute declarations. In particular:@@ -14,7 +14,7 @@ -- * If the attribute additionally carries an applicative effect, the 'Mapped' wrapper can be replaced by 'Traversed'. module Transformation.AG.Generics (-- * Type wrappers for automatic attribute inference- Auto(..), Folded(..), Mapped(..), Traversed(..),+ Auto(..), Keep(..), Folded(..), Mapped(..), Traversed(..), -- * Type classes replacing 'Attribution' Bequether(..), Synthesizer(..), SynthesizedField(..), Revelation(..), -- * The default behaviour on generic datatypes@@ -27,24 +27,68 @@ import Data.Kind (Type) import Data.Generics.Product.Subtype (Subtype(upcast)) import Data.Proxy (Proxy(..))+import Data.Semigroup (Semigroup(..)) import GHC.Generics import GHC.Records import GHC.TypeLits (Symbol, ErrorMessage (Text), TypeError) import Unsafe.Coerce (unsafeCoerce)-import Transformation (Transformation, Domain, Codomain)+import qualified Rank2+import Transformation (Transformation, Domain, Codomain, At) import Transformation.AG import qualified Transformation import qualified Transformation.Shallow as Shallow+import qualified Transformation.Deep as Deep+import qualified Transformation.Full as Full -- | Transformation wrapper that allows automatic inference of attribute rules. newtype Auto t = Auto t +-- | Transformation wrapper that allows automatic inference of attribute rules and preservation of all attributes with+-- the original nodes.+newtype Keep t = Keep t++type instance Atts (Inherited (Auto t)) x = Atts (Inherited t) x+type instance Atts (Synthesized (Auto t)) x = Atts (Synthesized t) x++type instance Atts (Inherited (Keep t)) x = Atts (Inherited t) x+type instance Atts (Synthesized (Keep t)) x = Atts (Synthesized t) x++instance {-# overlappable #-} (Revelation (Auto t), Domain (Auto t) ~ f, Codomain (Auto t) ~ Semantics (Auto t),+ Rank2.Apply (g (Semantics (Auto t))), Attribution (Auto t) g (Semantics (Auto t)) f) =>+ Auto t `At` g (Semantics (Auto t)) (Semantics (Auto t)) where+ t $ x = applyDefault (reveal t) t x+ {-# INLINE ($) #-}++instance {-# overlappable #-}+ (Revelation (Keep t), p ~ Transformation.Domain (Keep t), Rank2.Apply (g q),+ q ~ Transformation.Codomain (Keep t), q ~ PreservingSemantics (Keep t) p, s ~ Semantics (Keep t),+ Atts (Inherited (Keep t)) (g q q) ~ Atts (Inherited (Keep t)) (g s s),+ Atts (Synthesized (Keep t)) (g q q) ~ Atts (Synthesized (Keep t)) (g s s),+ g q (Synthesized (Keep t)) ~ g s (Synthesized (Keep t)),+ g q (Inherited (Keep t)) ~ g s (Inherited (Keep t)), Attribution (Keep t) g q p) =>+ Keep t `At` g (PreservingSemantics (Keep t) p) (PreservingSemantics (Keep t) p) where+ ($) :: Keep t -> p (g (PreservingSemantics (Keep t) p) (PreservingSemantics (Keep t) p))+ -> PreservingSemantics (Keep t) p (g (PreservingSemantics (Keep t) p) (PreservingSemantics (Keep t) p))+ t $ x = applyDefaultWithAttributes (reveal t) t x+ {-# INLINE ($) #-}++instance (Transformation (Auto t), Domain (Auto t) ~ f, Functor f, Codomain (Auto t) ~ Semantics (Auto t),+ Deep.Functor (Auto t) g, Auto t `At` g (Semantics (Auto t)) (Semantics (Auto t))) =>+ Full.Functor (Auto t) g where+ (<$>) = Full.mapUpDefault++instance (Transformation (Keep t), Domain (Keep t) ~ f, Functor f, Codomain (Keep t) ~ PreservingSemantics (Keep t) f,+ Functor f, Deep.Functor (Keep t) g,+ Keep t `At` g (PreservingSemantics (Keep t) f) (PreservingSemantics (Keep t) f)) =>+ Full.Functor (Keep t) g where+ (<$>) = Full.mapUpDefault+ instance {-# overlappable #-} (Bequether (Auto t) g d s, Synthesizer (Auto t) g d s) => Attribution (Auto t) g d s where attribution t l (Inherited i, s) = (Synthesized $ synthesis t l i s, bequest t l i s) -class (Transformation t, dom ~ Domain t) => Revelation t dom where+class Transformation t => Revelation t where -- | Extract the value from the transformation domain- reveal :: t -> dom x -> x+ reveal :: t -> Domain t x -> x -- | A half of the 'Attribution' class used to specify all inherited attributes. class Bequether t g deep shallow where@@ -59,7 +103,7 @@ class Synthesizer t g deep shallow where synthesis :: forall sem. sem ~ Semantics t => t -- ^ transformation - -> shallow (g deep deep) -- ^ tre node+ -> shallow (g deep deep) -- ^ tree node -> Atts (Inherited t) (g sem sem) -- ^ inherited attributes -> g sem (Synthesized t) -- ^ synthesized attributes -> Atts (Synthesized t) (g sem sem)@@ -74,13 +118,7 @@ -> g sem (Synthesized t) -- ^ synthesized attributes -> result -instance (Transformation t, Domain t ~ Identity) => Revelation t Identity where- reveal _ (Identity x) = x--instance (Transformation t, Domain t ~ (,) a) => Revelation t ((,) a) where- reveal _ (_, x) = x--instance {-# overlappable #-} (sem ~ Semantics t, Domain t ~ shallow, Revelation t shallow,+instance {-# overlappable #-} (sem ~ Semantics t, Domain t ~ shallow, Revelation t, Shallow.Functor (PassDown t sem (Atts (Inherited t) (g sem sem))) (g sem)) => Bequether t g (Semantics t) shallow where bequest = bequestDefault@@ -231,7 +269,7 @@ -- | The default 'bequest' method definition relies on generics to automatically pass down all same-named inherited -- attributes. bequestDefault :: forall t g shallow sem.- (sem ~ Semantics t, Domain t ~ shallow, Revelation t shallow,+ (sem ~ Semantics t, Domain t ~ shallow, Revelation t, Shallow.Functor (PassDown t sem (Atts (Inherited t) (g sem sem))) (g sem)) => t -> shallow (g sem sem) -> Atts (Inherited t) (g sem sem) -> g sem (Synthesized t) -> g sem (Inherited t)
+ src/Transformation/AG/Monomorphic.hs view
@@ -0,0 +1,153 @@+{-# Language DeriveDataTypeable, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RankNTypes,+ ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-}++-- | A special case of an attribute grammar where every node has only a single inherited and a single synthesized+-- attribute of the same monoidal type. The synthesized attributes of child nodes are all 'mconcat`ted together.++module Transformation.AG.Monomorphic where++import Data.Data (Data, Typeable)+import Data.Functor.Compose (Compose(..))+import Data.Functor.Const (Const(..))+import Data.Kind (Type)+import Data.Semigroup (Semigroup(..))+import qualified Rank2+import Transformation (Transformation, Domain, Codomain, At)+import qualified Transformation+import qualified Transformation.Deep as Deep+import qualified Transformation.Full as Full++-- | Transformation wrapper that allows automatic inference of attribute rules.+newtype Auto t = Auto t++-- | Transformation wrapper that allows automatic inference of attribute rules and preservation of the attribute with+-- the original nodes.+newtype Keep t = Keep t++data Atts a = Atts{+ inh :: a,+ syn :: a}+ deriving (Data, Typeable, Show)++instance Semigroup a => Semigroup (Atts a) where+ Atts i1 s1 <> Atts i2 s2 = Atts (i1 <> i2) (s1 <> s2)++instance Monoid a => Monoid (Atts a) where+ mappend = (<>)+ mempty = Atts mempty mempty++-- | A node's 'Semantics' maps its inherited attribute to its synthesized attribute.+type Semantics a = Const (a -> a)++-- | A node's 'PreservingSemantics' maps its inherited attribute to its synthesized attribute.+type PreservingSemantics f a = Compose ((->) a) (Compose ((,) (Atts a)) f)++-- | An attribution rule maps a node's inherited attribute and its child nodes' synthesized attribute to the node's+-- synthesized attribute and the children nodes' inherited attributes.+type Rule a = Atts a -> Atts a++instance {-# overlappable #-} Attribution t a g deep shallow where+ attribution = const (const id)++instance {-# overlappable #-} (Transformation (Auto t), p ~ Domain (Auto t), q ~ Codomain (Auto t), q ~ Semantics a,+ Rank2.Foldable (g q), Monoid a, Foldable p, Attribution (Auto t) a g q p) =>+ (Auto t) `At` g (Semantics a) (Semantics a) where+ ($) = applyDefault (foldr const $ error "Missing node")+ {-# INLINE ($) #-}++instance {-# overlappable #-} (Transformation (Keep t), p ~ Domain (Keep t), q ~ Codomain (Keep t),+ q ~ PreservingSemantics p a, Rank2.Foldable (g q), Monoid a,+ Foldable p, Functor p, Attribution (Keep t) a g q p) =>+ (Keep t) `At` g (PreservingSemantics p a) (PreservingSemantics p a) where+ ($) = applyDefaultWithAttributes+ {-# INLINE ($) #-}++instance (Transformation (Auto t), Domain (Auto t) ~ f, Functor f, Codomain (Auto t) ~ Semantics (Auto t),+ Deep.Functor (Auto t) g, Auto t `At` g (Semantics (Auto t)) (Semantics (Auto t))) =>+ Full.Functor (Auto t) g where+ (<$>) = Full.mapUpDefault++instance (Transformation (Keep t), Domain (Keep t) ~ f, Functor f, Codomain (Keep t) ~ PreservingSemantics f a,+ Functor f, Deep.Functor (Keep t) g,+ Keep t `At` g (PreservingSemantics f a) (PreservingSemantics f a)) =>+ Full.Functor (Keep t) g where+ (<$>) = Full.mapUpDefault++instance (Transformation (Keep t), Domain (Keep t) ~ f, Traversable f, Rank2.Traversable (g f),+ Codomain (Keep t) ~ PreservingSemantics f a, Deep.Traversable (Feeder a f) g, Full.Functor (Keep t) g,+ Keep t `At` g (PreservingSemantics f a) (PreservingSemantics f a)) =>+ Full.Traversable (Keep t) g where+ traverse = traverseDefaultWithAttributes++-- | The core function to tie the recursive knot, turning a 'Rule' for a node into its 'Semantics'.+knit :: (Rank2.Foldable (g sem), sem ~ Semantics a, Monoid a)+ => Rule a -> g sem sem -> sem (g sem sem)+knit r chSem = Const knitted+ where knitted inherited = synthesized+ where Atts{syn= synthesized, inh= chInh} = r Atts{inh= inherited, syn= chSyn}+ chSyn = Rank2.foldMap (($ chInh) . getConst) chSem++-- | Another way to tie the recursive knot, using a 'Rule' to add attributes to every node througha stateful calculation+knitKeeping :: forall a f g sem. (Rank2.Foldable (g sem), sem ~ PreservingSemantics f a,+ Monoid a, Foldable f, Functor f)+ => Rule a -> f (g sem sem) -> sem (g sem sem)+knitKeeping r x = Compose knitted+ where knitted :: a -> Compose ((,) (Atts a)) f (g sem sem)+ knitted inherited = Compose (results, x)+ where results@Atts{inh= chInh} = r Atts{inh= inherited, syn= chSyn}+ chSyn = foldMap (Rank2.foldMap (syn . fst . getCompose . ($ chInh) . getCompose)) x++-- | The core type class for defining the attribute grammar. The instances of this class typically have a form like+--+-- > instance Attribution MyAttGrammar MyMonoid MyNode (Semantics MyAttGrammar) Identity where+-- > attribution MyAttGrammar{} (Identity MyNode{})+-- > Atts{inh= fromParent,+-- > syn= fromChildren}+-- > = Atts{syn= toParent,+-- > inh= toChildren}+class Attribution t a g (deep :: Type -> Type) shallow where+ -- | The attribution rule for a given transformation and node.+ attribution :: t -> shallow (g deep deep) -> Rule a++-- | Drop-in implementation of 'Transformation.$'+applyDefault :: (p ~ Domain t, q ~ Semantics a, x ~ g q q, Rank2.Foldable (g q), Attribution t a g q p, Monoid a)+ => (forall y. p y -> y) -> t -> p x -> q x+applyDefault extract t x = knit (attribution t x) (extract x)+{-# INLINE applyDefault #-}++-- | Drop-in implementation of 'Full.<$>'+fullMapDefault :: (p ~ Domain t, q ~ Semantics a, q ~ Codomain t, x ~ g q q, Rank2.Foldable (g q),+ Deep.Functor t g, Attribution t a g p p, Monoid a)+ => (forall y. p y -> y) -> t -> p (g p p) -> q (g q q)+fullMapDefault extract t local = knit (attribution t local) (t Deep.<$> extract local)+{-# INLINE fullMapDefault #-}++-- | Drop-in implementation of 'Transformation.$' that stores all attributes with every original node+applyDefaultWithAttributes :: (p ~ Domain t, q ~ PreservingSemantics p a, x ~ g q q,+ Attribution t a g q p, Rank2.Foldable (g q), Monoid a, Foldable p, Functor p)+ => t -> p x -> q x+applyDefaultWithAttributes t x = knitKeeping (attribution t x) x+{-# INLINE applyDefaultWithAttributes #-}++-- | Drop-in implementation of 'Full.traverse' that stores all attributes with every original node+traverseDefaultWithAttributes :: forall t p q r a g.+ (Transformation t, Domain t ~ p, Codomain t ~ Compose ((->) a) q,+ q ~ Compose ((,) (Atts a)) p, r ~ Compose ((->) a) q,+ Traversable p, Full.Functor t g, Deep.Traversable (Feeder a p) g,+ Transformation.At t (g r r))+ => t -> p (g p p) -> a -> q (g q q)+traverseDefaultWithAttributes t x rootInheritance = Full.traverse Feeder (t Full.<$> x) rootInheritance+{-# INLINE traverseDefaultWithAttributes #-}++data Feeder a (f :: Type -> Type) = Feeder++instance Transformation (Feeder a f) where+ type Domain (Feeder a f) = Compose ((->) a) (Compose ((,) (Atts a)) f)+ type Codomain (Feeder a f) = Compose ((->) a) (Compose ((,) (Atts a)) f)++instance Transformation.At (Feeder a f) g where+ Feeder $ x = x++instance (Traversable f, Deep.Traversable (Feeder a f) g) => Full.Traversable (Feeder a f) g where+ traverse t x inheritance = Compose (atts{inh= inheritance}, traverse (Deep.traverse t) y (inh atts))+ where Compose (atts, y) = getCompose x inheritance
src/Transformation/Deep.hs view
@@ -12,6 +12,7 @@ import Data.Data (Data, Typeable) import Data.Functor.Compose (Compose) import Data.Functor.Const (Const)+import qualified Data.Functor as Rank1 import qualified Rank2 import qualified Data.Functor import Transformation (Transformation, Domain, Codomain)@@ -22,6 +23,7 @@ -- | Like "Transformation.Shallow".'Transformation.Shallow.Functor' except it maps all descendants and not only immediate children class (Transformation t, Rank2.Functor (g (Domain t))) => Functor t g where (<$>) :: t -> g (Domain t) (Domain t) -> g (Codomain t) (Codomain t)+ infixl 4 <$> -- | Like "Transformation.Shallow".'Transformation.Shallow.Foldable' except it folds all descendants and not only immediate children class (Transformation t, Rank2.Foldable (g (Domain t))) => Foldable t g where@@ -32,10 +34,14 @@ traverse :: Codomain t ~ Compose m f => t -> g (Domain t) (Domain t) -> m (g f f) -- | Like 'Data.Functor.Product.Product' for data types with two type constructor parameters-data Product g1 g2 (p :: * -> *) (q :: * -> *) = Pair{fst :: q (g1 p p),- snd :: q (g2 p p)}+data Product g h (d :: * -> *) (s :: * -> *) = Pair{fst :: s (g d d),+ snd :: s (h d d)} -instance Rank2.Functor (Product g1 g2 p) where+-- | Like 'Data.Functor.Sum.Sum' for data types with two type constructor parameters+data Sum g h (d :: * -> *) (s :: * -> *) = InL (s (g d d))+ | InR (s (h d d))++instance Rank2.Functor (Product g h p) where f <$> ~(Pair left right) = Pair (f left) (f right) instance Rank2.Apply (Product g h p) where@@ -68,6 +74,40 @@ Data (q (g1 p p)), Data (q (g2 p p))) => Data (Product g1 g2 p q) deriving instance (Show (q (g1 p p)), Show (q (g2 p p))) => Show (Product g1 g2 p q) +instance Rank2.Functor (Sum g h p) where+ f <$> InL left = InL (f left)+ f <$> InR right = InR (f right)++instance Rank2.Foldable (Sum g h p) where+ foldMap f (InL left) = f left+ foldMap f (InR right) = f right++instance Rank2.Traversable (Sum g h p) where+ traverse f (InL left) = InL Rank1.<$> f left+ traverse f (InR right) = InR Rank1.<$> f right++instance (Full.Functor t g, Full.Functor t h) => Functor t (Sum g h) where+ t <$> InL left = InL (t Full.<$> left)+ t <$> InR right = InR (t Full.<$> right)++instance (Full.Foldable t g, Full.Foldable t h, Codomain t ~ Const m) => Foldable t (Sum g h) where+ foldMap t (InL left) = Full.foldMap t left+ foldMap t (InR right) = Full.foldMap t right++instance (Full.Traversable t g, Full.Traversable t h, Codomain t ~ Compose m f, Applicative m) =>+ Traversable t (Sum g h) where+ traverse t (InL left) = InL Rank1.<$> Full.traverse t left+ traverse t (InR right) = InR Rank1.<$> Full.traverse t right++deriving instance (Typeable p, Typeable q, Typeable g1, Typeable g2,+ Data (q (g1 p p)), Data (q (g2 p p))) => Data (Sum g1 g2 p q)+deriving instance (Show (q (g1 p p)), Show (q (g2 p p))) => Show (Sum g1 g2 p q)+ -- | Alphabetical synonym for '<$>' fmap :: Functor t g => t -> g (Domain t) (Domain t) -> g (Codomain t) (Codomain t) fmap = (<$>)++-- | Equivalent of 'Data.Either.either'+eitherFromSum :: Sum g h d s -> Either (s (g d d)) (s (h d d))+eitherFromSum (InL left) = Left left+eitherFromSum (InR right) = Right right
src/Transformation/Deep/TH.hs view
@@ -6,7 +6,7 @@ -- > $(Transformation.Deep.TH.deriveFunctor ''MyDataType) -- -{-# Language TemplateHaskell #-}+{-# Language CPP, TemplateHaskell #-} -- Adapted from https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial module Transformation.Deep.TH (deriveAll, deriveFunctor, deriveTraversable)@@ -95,11 +95,18 @@ NewtypeD _ nm tyVars kind c _ -> return (nm, tyVars, kind, [c]) _ -> fail "deriveApply: tyCon may not be a type synonym." +#if MIN_VERSION_template_haskell(2,17,0)+ let (KindedTV tyVar _ (AppT (AppT ArrowT StarT) StarT) :+ KindedTV tyVar' _ (AppT (AppT ArrowT StarT) StarT) : _) = reverse tyVars+ apply t (PlainTV name _) = appT t (varT name)+ apply t (KindedTV name _ _) = appT t (varT name)+#else let (KindedTV tyVar (AppT (AppT ArrowT StarT) StarT) : KindedTV tyVar' (AppT (AppT ArrowT StarT) StarT) : _) = reverse tyVars- instanceType = foldl apply (conT tyConName) (reverse $ drop 2 $ reverse tyVars) apply t (PlainTV name) = appT t (varT name) apply t (KindedTV name _) = appT t (varT name)+#endif+ instanceType = foldl apply (conT tyConName) (reverse $ drop 2 $ reverse tyVars) putQ (Deriving tyConName tyVar' tyVar) return (instanceType, cs)
src/Transformation/Full.hs view
@@ -22,6 +22,7 @@ -- | Like "Transformation.Deep".'Deep.Functor' except it maps an additional wrapper around the entire tree class (Transformation t, Rank2.Functor (g (Domain t))) => Functor t g where (<$>) :: t -> Domain t (g (Domain t) (Domain t)) -> Codomain t (g (Codomain t) (Codomain t))+ infixl 4 <$> -- | Like "Transformation.Deep".'Deep.Foldable' except the entire tree is also wrapped class (Transformation t, Rank2.Foldable (g (Domain t))) => Foldable t g where@@ -49,9 +50,9 @@ Codomain t ~ Const m, Data.Foldable.Foldable (Domain t), Monoid m) => t -> Domain t (g (Domain t) (Domain t)) -> m -- | Default implementation for 'foldMap' that folds the wrapper and then the tree-foldMapDownDefault t x = getConst (t Transformation.$ x) <> Data.Foldable.foldMap (Deep.foldMap t) x+foldMapDownDefault t x = getConst (t Transformation.$ x) `mappend` Data.Foldable.foldMap (Deep.foldMap t) x -- | Default implementation for 'foldMap' that folds the tree and then the wrapper-foldMapUpDefault t x = Data.Foldable.foldMap (Deep.foldMap t) x <> getConst (t Transformation.$ x)+foldMapUpDefault t x = Data.Foldable.foldMap (Deep.foldMap t) x `mappend` getConst (t Transformation.$ x) -- | Default implementation for 'traverse' that traverses the wrapper and then the tree traverseDownDefault :: (Deep.Traversable t g, t `Transformation.At` g (Domain t) (Domain t),
src/Transformation/Rank2.hs view
@@ -15,6 +15,7 @@ -- | Transform (naturally) the containing functor of every node in the given tree. (<$>) :: Deep.Functor (Map p q) g => (forall a. p a -> q a) -> g p p -> g q q (<$>) f = (Deep.<$>) (Map f)+infixl 4 <$> -- | Fold the containing functor of every node in the given tree. foldMap :: (Deep.Foldable (Fold p m) g, Monoid m) => (forall a. p a -> m) -> g p p -> m
src/Transformation/Shallow.hs view
@@ -18,6 +18,7 @@ -- | Like Rank2.'Rank2.Functor' except it takes a 'Transformation' instead of a polymorphic function class (Transformation t, Rank2.Functor g) => Functor t g where (<$>) :: t -> g (Domain t) -> g (Codomain t)+ infixl 4 <$> -- | Like Rank2.'Rank2.Foldable' except it takes a 'Transformation' instead of a polymorphic function class (Transformation t, Rank2.Foldable g) => Foldable t g where@@ -31,7 +32,7 @@ t <$> Rank2.Pair left right = Rank2.Pair (t <$> left) (t <$> right) instance (Foldable t g, Foldable t h, Codomain t ~ Const m, Monoid m) => Foldable t (Rank2.Product g h) where- foldMap t (Rank2.Pair left right) = foldMap t left <> foldMap t right+ foldMap t (Rank2.Pair left right) = foldMap t left `mappend` foldMap t right instance (Traversable t g, Traversable t h, Codomain t ~ Compose m f, Applicative m) => Traversable t (Rank2.Product g h) where traverse t (Rank2.Pair left right) = liftA2 Rank2.Pair (traverse t left) (traverse t right)
src/Transformation/Shallow/TH.hs view
@@ -6,7 +6,7 @@ -- > $(Transformation.Shallow.TH.deriveFunctor ''MyDataType) -- -{-# Language TemplateHaskell #-}+{-# Language CPP, TemplateHaskell #-} -- Adapted from https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial module Transformation.Shallow.TH (deriveAll, deriveFunctor, deriveFoldable, deriveTraversable)@@ -91,10 +91,17 @@ NewtypeD _ nm tyVars kind c _ -> return (nm, tyVars, kind, [c]) _ -> fail "deriveApply: tyCon may not be a type synonym." +#if MIN_VERSION_template_haskell(2,17,0)+ let (KindedTV tyVar _ (AppT (AppT ArrowT StarT) StarT) : _) = reverse tyVars+ instanceType = foldl apply (conT tyConName) (reverse $ drop 1 $ reverse tyVars)+ apply t (PlainTV name _) = appT t (varT name)+ apply t (KindedTV name _ _) = appT t (varT name)+#else let (KindedTV tyVar (AppT (AppT ArrowT StarT) StarT) : _) = reverse tyVars instanceType = foldl apply (conT tyConName) (reverse $ drop 1 $ reverse tyVars) apply t (PlainTV name) = appT t (varT name) apply t (KindedTV name _) = appT t (varT name)+#endif putQ (Deriving tyConName tyVar) return (instanceType, cs)@@ -257,6 +264,8 @@ AppT ty a | ty == VarT typeVar -> (,) <$> ((:[]) <$> baseConstraint (pure a)) <*> (wrap (varE '(Transformation.$) `appE` trans) `appE` fieldAccess)+ AppT t1 t2 | t2 == VarT typeVar -> (,) <$> traverse shallowConstraint [pure t1]+ <*> appE (wrap [| ($trans Transformation.Shallow.<$>) |]) fieldAccess AppT t1 t2 | t1 /= VarT typeVar -> genShallowmapField trans t2 shallowConstraint baseConstraint fieldAccess (wrap . appE (varE '(<$>))) SigT ty _kind -> genShallowmapField trans ty shallowConstraint baseConstraint fieldAccess wrap@@ -272,6 +281,8 @@ (,) <$> ((:[]) <$> baseConstraint (pure a)) <*> (wrap (varE '(.) `appE` varE 'getConst `appE` (varE '(Transformation.$) `appE` trans)) `appE` fieldAccess)+ AppT t1 t2 | t2 == VarT typeVar -> (,) <$> traverse shallowConstraint [pure t1]+ <*> appE (wrap [| (Transformation.Shallow.foldMap $trans) |]) fieldAccess AppT t1 t2 | t1 /= VarT typeVar -> genFoldMapField trans t2 shallowConstraint baseConstraint fieldAccess (wrap . appE (varE 'foldMap)) SigT ty _kind -> genFoldMapField trans ty shallowConstraint baseConstraint fieldAccess wrap@@ -286,6 +297,8 @@ (,) <$> ((:[]) <$> baseConstraint (pure a)) <*> (wrap (varE '(.) `appE` varE 'getCompose `appE` (varE '(Transformation.$) `appE` trans)) `appE` fieldAccess)+ AppT t1 t2 | t2 == VarT typeVar -> (,) <$> traverse shallowConstraint [pure t1]+ <*> appE (wrap [| (Transformation.Shallow.traverse $trans) |]) fieldAccess AppT t1 t2 | t1 /= VarT typeVar -> genTraverseField trans t2 shallowConstraint baseConstraint fieldAccess (wrap . appE (varE 'traverse)) SigT ty _kind -> genTraverseField trans ty shallowConstraint baseConstraint fieldAccess wrap
test/README.lhs view
@@ -31,6 +31,7 @@ import Data.Coerce (coerce) import Data.Functor.Const import Data.Functor.Identity+import Data.Monoid import qualified Rank2 import Transformation (Transformation, At) import qualified Transformation@@ -279,11 +280,17 @@ type Domain DeadCodeEliminator = Identity type Codomain DeadCodeEliminator = AG.Semantics DeadCodeEliminator +instance DeadCodeEliminator `Transformation.At` Decl Sem Sem where+ ($) = AG.applyDefault runIdentity++instance DeadCodeEliminator `Transformation.At` Expr Sem Sem where+ ($) = AG.applyDefault runIdentity+ instance Full.Functor DeadCodeEliminator Decl where- (<$>) = AG.fullMapDefault runIdentity+ (<$>) = Full.mapUpDefault instance Full.Functor DeadCodeEliminator Expr where- (<$>) = AG.fullMapDefault runIdentity+ (<$>) = Full.mapUpDefault ~~~ We also need another bit of a boilerplate instance that can be automatically generated with Template Haskell functions@@ -359,11 +366,11 @@ because they don't have any children. ~~~ {.haskell}-instance AG.Attribution DeadCodeEliminator Expr Identity Identity where- attribution DeadCodeEliminator (Identity e@(EVar v)) (AG.Inherited env, _) =- (AG.Synthesized (maybe e id $ env v), EVar v)- attribution DeadCodeEliminator (Identity e@(Con n)) (AG.Inherited env, _) =- (AG.Synthesized e, Con n)+instance AG.Attribution DeadCodeEliminator Expr Sem Identity where+ attribution DeadCodeEliminator (Identity (EVar v)) (AG.Inherited env, _) =+ (AG.Synthesized (maybe (EVar v) id $ env v), EVar v)+ attribution DeadCodeEliminator (Identity (Con n)) (AG.Inherited env, _) =+ (AG.Synthesized (Con n), Con n) ~~~ The `Add` and `Mul` nodes' rules need only to pass their inheritance down and to re-join the synthesized child@@ -388,7 +395,7 @@ attribution DeadCodeEliminator (Identity (Let _decl expr)) (AG.Inherited env, (Let (AG.Synthesized ~(env', decl')) (AG.Synthesized expr'))) = (AG.Synthesized (maybe id (bin Let) decl' expr'),- Let (AG.Inherited (env, Full.foldMap GetVariables expr)) (AG.Inherited $ \v-> env' v <|> env v))+ Let (AG.Inherited (env, Deep.foldMap GetVariables expr')) (AG.Inherited $ \v-> env' v <|> env v)) ~~~ ### Declaration rules@@ -396,7 +403,7 @@ The rules for `Decl` are a bit more involved. ~~~ {.haskell}-instance AG.Attribution DeadCodeEliminator Decl Identity Identity where+instance AG.Attribution DeadCodeEliminator Decl Sem Identity where ~~~ A single variable binding can be in three distinct situations. If the variable is not referenced at all, we can just
test/RepMin.hs view
@@ -1,4 +1,4 @@-{-# Language FlexibleInstances, MultiParamTypeClasses, RankNTypes, StandaloneDeriving, +{-# Language FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TypeFamilies, UndecidableInstances #-} -- | The RepMin example - replicate a binary tree with all leaves replaced by the minimal leaf value.@@ -35,7 +35,7 @@ Leaf f <*> ~(Leaf x) = Leaf (Rank2.apply f x) instance Rank2.Applicative (Tree a f') where- pure = Leaf+ pure x = Leaf x instance Rank2.Apply (Root a f') where Root f <*> ~(Root x) = Root (Rank2.apply f x)@@ -50,9 +50,11 @@ -- | The transformation type data RepMin = RepMin +type Sem = AG.Semantics RepMin+ instance Transformation RepMin where type Domain RepMin = Identity- type Codomain RepMin = AG.Semantics RepMin+ type Codomain RepMin = Sem -- | Inherited attributes' type data InhRepMin = InhRepMin{global :: Int}@@ -68,24 +70,29 @@ type instance AG.Atts (Inherited RepMin) (Root Int f' f) = () type instance AG.Atts (Synthesized RepMin) (Root Int f' f) = SynRepMin -type instance AG.Atts (Inherited a) Int = ()-type instance AG.Atts (Synthesized a) Int = Int+type instance AG.Atts (Inherited RepMin) Int = ()+type instance AG.Atts (Synthesized RepMin) Int = Int +instance Transformation.At RepMin (Tree Int Sem Sem) where+ ($) = AG.applyDefault runIdentity+instance Transformation.At RepMin (Root Int Sem Sem) where+ ($) = AG.applyDefault runIdentity+ instance Full.Functor RepMin (Tree Int) where- (<$>) = AG.fullMapDefault runIdentity+ (<$>) = Full.mapUpDefault instance Full.Functor RepMin (Root Int) where- (<$>) = AG.fullMapDefault runIdentity+ (<$>) = Full.mapUpDefault -- | The semantics of the primitive 'Int' type must be defined manually. instance Transformation.At RepMin Int where RepMin $ Identity n = Rank2.Arrow (const $ Synthesized n) -instance AG.Attribution RepMin (Root Int) Identity Identity where+instance AG.Attribution RepMin (Root Int) Sem Identity where attribution RepMin self (inherited, Root root) = (Synthesized SynRepMin{local= local (syn root), tree= tree (syn root)}, Root{root= Inherited InhRepMin{global= local (syn root)}}) -instance AG.Attribution RepMin (Tree Int) Identity Identity where+instance AG.Attribution RepMin (Tree Int) Sem Identity where attribution _ _ (inherited, Fork left right) = (Synthesized SynRepMin{local= local (syn left) `min` local (syn right), tree= tree (syn left) `fork` tree (syn right)},
test/RepMinAuto.hs view
@@ -1,4 +1,4 @@-{-# Language DataKinds, DeriveGeneric, DuplicateRecordFields, FlexibleInstances, MultiParamTypeClasses, RankNTypes,+{-# Language DataKinds, DeriveGeneric, DuplicateRecordFields, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TemplateHaskell, TypeFamilies, UndecidableInstances #-} -- | The RepMin example with automatic derivation of attributes.@@ -36,10 +36,6 @@ [Rank2.TH.deriveFunctor, Rank2.TH.deriveFoldable, Rank2.TH.deriveTraversable, Rank2.TH.unsafeDeriveApply, Transformation.Shallow.TH.deriveAll, Transformation.Deep.TH.deriveAll])) -instance (Transformation t, Transformation.At t a, Transformation.At t (Tree a (Codomain t) (Codomain t)),- Functor (Domain t)) => Full.Functor t (Tree a) where- (<$>) = Full.mapUpDefault- -- | The transformation type. It will always appear wrapped in 'Auto' to enable automatic attribute derivation. data RepMin = RepMin @@ -50,6 +46,9 @@ type Domain (Auto RepMin) = Identity type Codomain (Auto RepMin) = Sem +instance AG.Revelation (Auto RepMin) where+ reveal (Auto RepMin) = runIdentity+ -- | Inherited attributes' type data InhRepMin = InhRepMin{global :: Int} deriving (Generic, Show)@@ -66,18 +65,13 @@ tree :: AG.Mapped Identity Int} deriving (Generic, Show) -type instance AG.Atts (Inherited (Auto RepMin)) (Tree Int f' f) = InhRepMin-type instance AG.Atts (Synthesized (Auto RepMin)) (Tree Int f' f) = SynRepMin Tree-type instance AG.Atts (Inherited (Auto RepMin)) (Root Int f' f) = ()-type instance AG.Atts (Synthesized (Auto RepMin)) (Root Int f' f) = SynRepMin Root--type instance AG.Atts (Inherited a) Int = InhRepMin-type instance AG.Atts (Synthesized a) Int = SynRepLeaf+type instance AG.Atts (Inherited RepMin) (Tree Int f' f) = InhRepMin+type instance AG.Atts (Synthesized RepMin) (Tree Int f' f) = SynRepMin Tree+type instance AG.Atts (Inherited RepMin) (Root Int f' f) = ()+type instance AG.Atts (Synthesized RepMin) (Root Int f' f) = SynRepMin Root -instance Transformation.At (Auto RepMin) (Tree Int Sem Sem) where- ($) = AG.applyDefault runIdentity-instance Transformation.At (Auto RepMin) (Root Int Sem Sem) where- ($) = AG.applyDefault runIdentity+type instance AG.Atts (Inherited RepMin) Int = InhRepMin+type instance AG.Atts (Synthesized RepMin) Int = SynRepLeaf -- | The semantics of the primitive 'Int' type must be defined manually. instance Transformation.At (Auto RepMin) Int where