rank2classes 1.4.4 → 1.4.5
raw patch · 4 files changed
+182/−61 lines, 4 filesdep +data-functor-logisticdep ~template-haskellPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: data-functor-logistic
Dependency ranges changed: template-haskell
API changes (from Hackage documentation)
- Rank2: instance forall k (f :: (k -> *) -> *) (g :: (k -> *) -> *). (Rank2.Distributive f, Rank2.Distributive g) => Rank2.Distributive (f GHC.Generics.:*: g)
- Rank2: instance forall k (f :: (k -> *) -> *) i (c :: GHC.Generics.Meta). Rank2.Distributive f => Rank2.Distributive (GHC.Generics.M1 i c f)
- Rank2: instance forall k (f :: (k -> *) -> *). Rank2.Distributive f => Rank2.Distributive (GHC.Generics.Rec1 f)
- Rank2: instance forall k (g :: (k -> *) -> *) (h :: (k -> *) -> *). (Rank2.Distributive g, Rank2.Distributive h) => Rank2.Distributive (Data.Functor.Product.Product g h)
- Rank2: instance forall k (g :: (k -> *) -> *) (p :: * -> *). (Rank2.Distributive g, Data.Distributive.Distributive p) => Rank2.Distributive (Rank2.Compose g p)
- Rank2: instance forall k (g :: (k -> *) -> *). Rank2.Distributive g => Rank2.Distributive (Rank2.Identity g)
- Rank2: instance forall k (x :: k). Rank2.Distributive (Rank2.Only x)
+ Rank2: class Functor g => Logistic g
+ Rank2: deliver :: (Logistic g, Contravariant p) => p (g q -> g q) -> g (Compose p (q ~> q))
+ Rank2: getters :: Distributive g => g (Compose ((->) (g f)) f)
+ Rank2: instance Rank2.Logistic Data.Proxy.Proxy
+ Rank2: instance Rank2.Logistic Rank2.Empty
+ Rank2: instance forall k1 (f :: (k1 -> *) -> *) (g :: (k1 -> *) -> *). (Rank2.Distributive f, Rank2.Distributive g) => Rank2.Distributive (f GHC.Generics.:*: g)
+ Rank2: instance forall k1 (f :: (k1 -> *) -> *) (g :: (k1 -> *) -> *). (Rank2.Logistic f, Rank2.Logistic g) => Rank2.Logistic (f GHC.Generics.:*: g)
+ Rank2: instance forall k1 (f :: (k1 -> *) -> *) i (c :: GHC.Generics.Meta). Rank2.Distributive f => Rank2.Distributive (GHC.Generics.M1 i c f)
+ Rank2: instance forall k1 (f :: (k1 -> *) -> *) i (c :: GHC.Generics.Meta). Rank2.Logistic f => Rank2.Logistic (GHC.Generics.M1 i c f)
+ Rank2: instance forall k1 (f :: (k1 -> *) -> *). Rank2.Distributive f => Rank2.Distributive (GHC.Generics.Rec1 f)
+ Rank2: instance forall k1 (f :: (k1 -> *) -> *). Rank2.Logistic f => Rank2.Logistic (GHC.Generics.Rec1 f)
+ Rank2: instance forall k1 (g :: (k1 -> *) -> *) (h :: (k1 -> *) -> *). (Rank2.Distributive g, Rank2.Distributive h) => Rank2.Distributive (Data.Functor.Product.Product g h)
+ Rank2: instance forall k1 (g :: (k1 -> *) -> *) (h :: (k1 -> *) -> *). (Rank2.Logistic g, Rank2.Logistic h) => Rank2.Logistic (Data.Functor.Product.Product g h)
+ Rank2: instance forall k1 (g :: (k1 -> *) -> *) (p :: * -> *). (Rank2.Distributive g, Data.Distributive.Distributive p) => Rank2.Distributive (Rank2.Compose g p)
+ Rank2: instance forall k1 (g :: (k1 -> *) -> *) (p :: * -> *). (Rank2.Logistic g, Data.Functor.Logistic.Logistic p) => Rank2.Logistic (Rank2.Compose g p)
+ Rank2: instance forall k1 (g :: (k1 -> *) -> *). Rank2.Distributive g => Rank2.Distributive (Rank2.Identity g)
+ Rank2: instance forall k1 (g :: (k1 -> *) -> *). Rank2.Logistic g => Rank2.Logistic (Rank2.Identity g)
+ Rank2: instance forall k1 (x :: k1). Rank2.Distributive (Rank2.Only x)
+ Rank2: instance forall k1 (x :: k1). Rank2.Logistic (Rank2.Only x)
+ Rank2: setters :: Logistic g => g ((f ~> f) ~> Const (g f -> g f))
+ Rank2.TH: deriveLogistic :: Name -> Q [Dec]
- Rank2: class Functor g => DistributiveTraversable (g :: (k -> *) -> *)
+ Rank2: class Functor g => DistributiveTraversable (g :: (k -> Type) -> Type)
- Rank2: collect :: (Distributive g, Functor f1) => (a -> g f2) -> f1 a -> g (Compose f1 f2)
+ Rank2: collect :: (Distributive g, Functor p) => (a -> g q) -> p a -> g (Compose p q)
- Rank2: distribute :: (Distributive g, Functor f1) => f1 (g f2) -> g (Compose f1 f2)
+ Rank2: distribute :: (Distributive g, Functor p) => p (g q) -> g (Compose p q)
- Rank2: liftA2TraverseBoth :: (Apply g, DistributiveTraversable g, Traversable f1, Traversable f2) => (forall a. f1 (t a) -> f2 (u a) -> v a) -> f1 (g t) -> f2 (g u) -> g v
+ Rank2: liftA2TraverseBoth :: forall f1 f2 g t u v. (Apply g, DistributiveTraversable g, Traversable f1, Traversable f2) => (forall a. f1 (t a) -> f2 (u a) -> v a) -> f1 (g t) -> f2 (g u) -> g v
Files
- CHANGELOG.md +7/−0
- rank2classes.cabal +4/−3
- src/Rank2.hs +74/−10
- src/Rank2/TH.hs +97/−48
CHANGELOG.md view
@@ -1,3 +1,10 @@+Version 1.4.5+---------------+* Added the `Logistic` type class, `getters` and `setters`+* Added `Rank2.TH.deriveLogistic`, included it in `deriveAll`+* Compiling with GHC 9.4.2+* Forward compatibility with `TypeFamilies`+ Version 1.4.4 --------------- * Tested with GHC 9.2.1, incremented the upper `template-haskell` dependency bound
rank2classes.cabal view
@@ -1,5 +1,5 @@ name: rank2classes-version: 1.4.4+version: 1.4.5 synopsis: standard type constructor class hierarchy, only with methods of rank 2 types description: A mirror image of the standard type constructor class hierarchy rooted in 'Functor', except with methods of rank 2@@ -40,10 +40,11 @@ ghc-options: -Wall build-depends: base >=4.10 && <5, transformers >= 0.5 && < 0.7,- distributive < 0.7+ distributive < 0.7,+ data-functor-logistic < 0.1 if flag(use-template-haskell)- build-depends: template-haskell >= 2.11 && < 2.19+ build-depends: template-haskell >= 2.11 && < 2.20 exposed-modules: Rank2.TH test-suite doctests
src/Rank2.hs view
@@ -8,16 +8,18 @@ {-# LANGUAGE DefaultSignatures, InstanceSigs, KindSignatures, PolyKinds, Rank2Types #-} {-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-} {-# LANGUAGE EmptyCase #-}+{-# LANGUAGE TypeApplications #-} module Rank2 ( -- * Rank 2 classes Functor(..), Apply(..), Applicative(..),- Foldable(..), Traversable(..), Distributive(..), DistributiveTraversable(..), distributeJoin,+ Foldable(..), Traversable(..), Distributive(..), DistributiveTraversable(..), Logistic(..), distributeJoin, -- * Rank 2 data types Compose(..), Empty(..), Only(..), Flip(..), Identity(..), Product(..), Sum(..), Arrow(..), type (~>), -- * Method synonyms and helper functions ($), fst, snd, ap, fmap, liftA4, liftA5, fmapTraverse, liftA2Traverse1, liftA2Traverse2, liftA2TraverseBoth,- distributeWith, distributeWithTraversable)+ distributeWith, distributeWithTraversable,+ getters, setters) where import qualified Control.Applicative as Rank1@@ -25,6 +27,8 @@ import qualified Data.Foldable as Rank1 import qualified Data.Traversable as Rank1 import qualified Data.Functor.Compose as Rank1+import qualified Data.Functor.Contravariant as Rank1+import qualified Data.Functor.Logistic as Rank1 import qualified Data.Distributive as Rank1 import Data.Coerce (coerce) import Data.Semigroup (Semigroup(..))@@ -32,6 +36,7 @@ import Data.Functor.Const (Const(..)) import Data.Functor.Product (Product(Pair)) import Data.Functor.Sum (Sum(InL, InR))+import Data.Kind (Type) import Data.Proxy (Proxy(..)) import qualified GHC.Generics as Generics @@ -69,7 +74,6 @@ sequence :: Rank1.Applicative m => g (Rank1.Compose m p) -> m (g p) traverse f = sequence . fmap (Rank1.Compose . f) sequence = traverse Rank1.getCompose- -- | Wrapper for functions that map the argument constructor type newtype Arrow p q a = Arrow{apply :: p a -> q a} @@ -113,17 +117,17 @@ -- | Equivalent of 'Rank1.Distributive' for rank 2 data types class DistributiveTraversable g => Distributive g where {-# MINIMAL cotraverse|distribute #-}- collect :: Rank1.Functor f1 => (a -> g f2) -> f1 a -> g (Rank1.Compose f1 f2)- distribute :: Rank1.Functor f1 => f1 (g f2) -> g (Rank1.Compose f1 f2)+ collect :: Rank1.Functor p => (a -> g q) -> p a -> g (Rank1.Compose p q)+ distribute :: Rank1.Functor p => p (g q) -> g (Rank1.Compose p q) -- | Dual of 'traverse', equivalent of 'Rank1.cotraverse' for rank 2 data types cotraverse :: Rank1.Functor m => (forall a. m (p a) -> q a) -> m (g p) -> g q collect f = distribute . Rank1.fmap f distribute = cotraverse Rank1.Compose- cotraverse f = (fmap (f . Rank1.getCompose)) . distribute+ cotraverse f = fmap (f . Rank1.getCompose) . distribute -- | A weaker 'Distributive' that requires 'Rank1.Traversable' to use, not just a 'Rank1.Functor'.-class Functor g => DistributiveTraversable (g :: (k -> *) -> *) where+class Functor g => DistributiveTraversable (g :: (k -> Type) -> Type) where collectTraversable :: Rank1.Traversable f1 => (a -> g f2) -> f1 a -> g (Rank1.Compose f1 f2) distributeTraversable :: Rank1.Traversable f1 => f1 (g f2) -> g (Rank1.Compose f1 f2) cotraverseTraversable :: Rank1.Traversable f1 => (forall x. f1 (f2 x) -> f x) -> f1 (g f2) -> g f@@ -135,6 +139,10 @@ (forall a. m (p a) -> q a) -> m (g p) -> g q cotraverseTraversable = cotraverse +-- | Equivalent of 'Rank1.Logistic' for rank 2 data types+class Functor g => Logistic g where+ deliver :: Rank1.Contravariant p => p (g q -> g q) -> g (Rank1.Compose p (q ~> q))+ -- | A variant of 'distribute' convenient with 'Rank1.Monad' instances distributeJoin :: (Distributive g, Rank1.Monad f) => f (g f) -> g f distributeJoin = cotraverse Rank1.join@@ -154,11 +162,21 @@ liftA2Traverse2 f x y = liftA2 (\x' y' -> f x' (Rank1.getCompose y')) x (distributeTraversable y) -- | Like 'liftA2', but traverses over both its arguments-liftA2TraverseBoth :: (Apply g, DistributiveTraversable g, Rank1.Traversable f1, Rank1.Traversable f2) =>+liftA2TraverseBoth :: forall f1 f2 g t u v.+ (Apply g, DistributiveTraversable g, Rank1.Traversable f1, Rank1.Traversable f2) => (forall a. f1 (t a) -> f2 (u a) -> v a) -> f1 (g t) -> f2 (g u) -> g v liftA2TraverseBoth f x y = liftA2 applyCompose (distributeTraversable x) (distributeTraversable y)- where applyCompose x' y' = f (Rank1.getCompose x') (Rank1.getCompose y')+ where applyCompose :: forall a. Rank1.Compose f1 t a -> Rank1.Compose f2 u a -> v a+ applyCompose x' y' = f (Rank1.getCompose x') (Rank1.getCompose y') +-- | Enumerate getters for each element+getters :: Distributive g => g (Rank1.Compose ((->) (g f)) f)+getters = distribute id++-- | Enumerate setters for each element+setters :: Logistic g => g ((f ~> f) ~> Const (g f -> g f))+setters = Arrow . (Const .) . Rank1.getOp . Rank1.getCompose <$> deliver (Rank1.Op id)+ {-# DEPRECATED distributeWith "Use cotraverse instead." #-} -- | Synonym for 'cotraverse' distributeWith :: (Distributive g, Rank1.Functor f) => (forall i. f (a i) -> b i) -> f (g a) -> g b@@ -194,7 +212,7 @@ instance Monoid (g (f a)) => Monoid (Flip g a f) where mempty = Flip mempty- Flip x `mappend` Flip y = Flip (x `mappend` y)+ mappend = (<>) instance Rank1.Functor g => Rank2.Functor (Flip g a) where f <$> Flip g = Flip (f Rank1.<$> g)@@ -498,3 +516,49 @@ cotraverse w f = Generics.Rec1 (cotraverse w (Rank1.fmap Generics.unRec1 f)) instance (Distributive f, Distributive g) => Distributive ((Generics.:*:) f g) where cotraverse w f = cotraverse w (Rank1.fmap (\(a Generics.:*: _) -> a) f) Generics.:*: cotraverse w (Rank1.fmap (\(_ Generics.:*: b) -> b) f)++instance Logistic Empty where+ deliver _ = Empty++instance Logistic Proxy where+ deliver _ = Proxy++instance Logistic (Only x) where+ deliver f = Only (Rank1.Compose (Rank1.contramap coerce f))++instance Logistic g => Logistic (Identity g) where+ deliver f = Identity (deliver (Rank1.contramap coerce f))++instance (Logistic g, Rank1.Logistic p) => Logistic (Compose g p) where+ deliver = Compose+ . fmap (inRank1Compose (Rank1.fmap (Rank1.Compose . Rank1.contramap apply)+ . Rank1.deliver+ . Rank1.contramap (Arrow . inRank1Compose)))+ . deliver+ . Rank1.contramap inCompose++inCompose :: (g (Rank1.Compose p q) -> g' (Rank1.Compose p' q')) -> Compose g p q -> Compose g' p' q'+inCompose f = Compose . f . getCompose++inRank1Compose :: (p (q a) -> p' (q' a')) -> Rank1.Compose p q a -> Rank1.Compose p' q' a'+inRank1Compose f = Rank1.Compose . f . Rank1.getCompose++instance (Logistic g, Logistic h) => Logistic (Product g h) where+ deliver f = Pair (deliver (Rank1.contramap first f)) (deliver (Rank1.contramap second f))++first :: (g p -> g' p) -> Product g h p -> Product g' h p+first f (Pair g h) = Pair (f g) h++second :: (h p -> h' p) -> Product g h p -> Product g h' p+second f (Pair g h) = Pair g (f h)++instance Logistic f => Logistic (Generics.M1 i c f) where+ deliver f = Generics.M1 (deliver (Rank1.contramap (\f'-> Generics.M1 . f' . Generics.unM1) f))++instance Logistic f => Logistic (Generics.Rec1 f) where+ deliver f = Generics.Rec1 (deliver (Rank1.contramap (\f'-> Generics.Rec1 . f' . Generics.unRec1) f))++instance (Logistic f, Logistic g) => Logistic ((Generics.:*:) f g) where+ deliver f = deliver (Rank1.contramap (\f' (a Generics.:*: b) -> f' a Generics.:*: b) f)+ Generics.:*:+ deliver (Rank1.contramap (\f' (a Generics.:*: b) -> a Generics.:*: f' b) f)
src/Rank2/TH.hs view
@@ -12,15 +12,22 @@ -- Adapted from https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial module Rank2.TH (deriveAll, deriveFunctor, deriveApply, unsafeDeriveApply, deriveApplicative,- deriveFoldable, deriveTraversable, deriveDistributive, deriveDistributiveTraversable)+ deriveFoldable, deriveTraversable,+ deriveDistributive, deriveDistributiveTraversable, deriveLogistic) where import Control.Applicative (liftA2, liftA3) import Control.Monad (replicateM) import Data.Distributive (cotraverse)+import Data.Functor.Compose (Compose (Compose))+import Data.Functor.Contravariant (contramap)+import Data.Functor.Logistic (deliver) import Data.Monoid ((<>))-import Language.Haskell.TH-import Language.Haskell.TH.Syntax (BangType, VarBangType, getQ, putQ)+import qualified Language.Haskell.TH as TH+import Language.Haskell.TH (Q, TypeQ, Name, TyVarBndr(KindedTV, PlainTV), Clause, Dec(..), Con(..), Type(..), Exp(..),+ Inline(Inlinable, Inline), RuleMatch(FunLike), Phases(AllPhases),+ appE, conE, conP, instanceD, varE, varP, normalB, pragInlD, recConE, recUpdE, wildP)+import Language.Haskell.TH.Syntax (BangType, VarBangType, Info(TyConI), getQ, putQ, newName) import qualified Rank2 @@ -28,21 +35,22 @@ deriveAll :: Name -> Q [Dec] deriveAll ty = foldr f (pure []) [deriveFunctor, deriveApply, deriveApplicative,- deriveFoldable, deriveTraversable, deriveDistributive, deriveDistributiveTraversable]+ deriveFoldable, deriveTraversable,+ deriveDistributive, deriveDistributiveTraversable, deriveLogistic] where f derive rest = (<>) <$> derive ty <*> rest deriveFunctor :: Name -> Q [Dec] deriveFunctor ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Functor ty (constraints, dec) <- genFmap cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, pragInlD '(Rank2.<$>) Inline FunLike AllPhases]] deriveApply :: Name -> Q [Dec] deriveApply ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Apply ty (constraints, dec) <- genAp cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, genLiftA2 cs, genLiftA3 cs, pragInlD '(Rank2.<*>) Inlinable FunLike AllPhases, pragInlD 'Rank2.liftA2 Inlinable FunLike AllPhases]]@@ -52,7 +60,7 @@ unsafeDeriveApply ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Apply ty (constraints, dec) <- genApUnsafely cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, genLiftA2Unsafely cs, genLiftA3Unsafely cs, pragInlD '(Rank2.<*>) Inlinable FunLike AllPhases, pragInlD 'Rank2.liftA2 Inlinable FunLike AllPhases]]@@ -61,39 +69,46 @@ deriveApplicative ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Applicative ty (constraints, dec) <- genPure cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, pragInlD 'Rank2.pure Inline FunLike AllPhases]] deriveFoldable :: Name -> Q [Dec] deriveFoldable ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Foldable ty (constraints, dec) <- genFoldMap cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, pragInlD 'Rank2.foldMap Inlinable FunLike AllPhases]] deriveTraversable :: Name -> Q [Dec] deriveTraversable ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Traversable ty (constraints, dec) <- genTraverse cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, pragInlD 'Rank2.traverse Inlinable FunLike AllPhases]] deriveDistributive :: Name -> Q [Dec] deriveDistributive ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Distributive ty (constraints, dec) <- genCotraverse cs- sequence [instanceD (cxt $ map pure constraints) instanceType+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec, pragInlD 'Rank2.cotraverse Inline FunLike AllPhases]] deriveDistributiveTraversable :: Name -> Q [Dec] deriveDistributiveTraversable ty = do (instanceType, cs) <- reifyConstructors ''Rank2.DistributiveTraversable ty (constraints, dec) <- genCotraverseTraversable cs- sequence [instanceD (cxt $ map pure constraints) instanceType [pure dec]]+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType [pure dec]] +deriveLogistic :: Name -> Q [Dec]+deriveLogistic ty = do+ (instanceType, cs) <- reifyConstructors ''Rank2.Logistic ty+ (constraints, dec) <- genDeliver cs+ sequence [instanceD (TH.cxt $ map pure constraints) instanceType+ [pure dec, pragInlD 'Rank2.deliver Inline FunLike AllPhases]]+ reifyConstructors :: Name -> Name -> Q (TypeQ, [Con]) reifyConstructors cls ty = do- (TyConI tyCon) <- reify ty+ (TyConI tyCon) <- TH.reify ty (tyConName, tyVars, _kind, cs) <- case tyCon of DataD _ nm tyVars kind cs _ -> return (nm, tyVars, kind, cs) NewtypeD _ nm tyVars kind c _ -> return (nm, tyVars, kind, [c])@@ -101,14 +116,14 @@ #if MIN_VERSION_template_haskell(2,17,0) let (KindedTV tyVar () (AppT (AppT ArrowT _) StarT)) = last tyVars- instanceType = conT cls `appT` foldl apply (conT tyConName) (init tyVars)- apply t (PlainTV name _) = appT t (varT name)- apply t (KindedTV name _ _) = appT t (varT name)+ instanceType = TH.conT cls `TH.appT` foldl apply (TH.conT tyConName) (init tyVars)+ apply t (PlainTV name _) = TH.appT t (TH.varT name)+ apply t (KindedTV name _ _) = TH.appT t (TH.varT name) #else let (KindedTV tyVar (AppT (AppT ArrowT _) StarT)) = last tyVars- instanceType = conT cls `appT` foldl apply (conT tyConName) (init tyVars)- apply t (PlainTV name) = appT t (varT name)- apply t (KindedTV name _) = appT t (varT name)+ instanceType = TH.conT cls `TH.appT` foldl apply (TH.conT tyConName) (init tyVars)+ apply t (PlainTV name) = TH.appT t (TH.varT name)+ apply t (KindedTV name _) = TH.appT t (TH.varT name) #endif putQ (Deriving tyConName tyVar)@@ -123,20 +138,20 @@ return (constraints, FunD '(Rank2.<*>) [clause]) genLiftA2 :: [Con] -> Q Dec-genLiftA2 [con] = funD 'Rank2.liftA2 [genLiftA2Clause False con]+genLiftA2 [con] = TH.funD 'Rank2.liftA2 [genLiftA2Clause False con] genLiftA3 :: [Con] -> Q Dec-genLiftA3 [con] = funD 'Rank2.liftA3 [genLiftA3Clause False con]+genLiftA3 [con] = TH.funD 'Rank2.liftA3 [genLiftA3Clause False con] genApUnsafely :: [Con] -> Q ([Type], Dec) genApUnsafely cons = do (constraints, clauses) <- unzip <$> mapM (genApClause True) cons return (concat constraints, FunD '(Rank2.<*>) clauses) genLiftA2Unsafely :: [Con] -> Q Dec-genLiftA2Unsafely cons = funD 'Rank2.liftA2 (genLiftA2Clause True <$> cons)+genLiftA2Unsafely cons = TH.funD 'Rank2.liftA2 (genLiftA2Clause True <$> cons) genLiftA3Unsafely :: [Con] -> Q Dec-genLiftA3Unsafely cons = funD 'Rank2.liftA3 (genLiftA3Clause True <$> cons)+genLiftA3Unsafely cons = TH.funD 'Rank2.liftA3 (genLiftA3Clause True <$> cons) genPure :: [Con] -> Q ([Type], Dec) genPure cs = do (constraints, clauses) <- unzip <$> mapM genPureClause cs@@ -158,6 +173,10 @@ genCotraverseTraversable [con] = do (constraints, clause) <- genCotraverseTraversableClause con return (constraints, FunD 'Rank2.cotraverseTraversable [clause]) +genDeliver :: [Con] -> Q ([Type], Dec)+genDeliver [con] = do (constraints, clause) <- genDeliverClause con+ return (constraints, FunD 'Rank2.deliver [clause])+ genFmapClause :: Con -> Q ([Type], Clause) genFmapClause (NormalC name fieldTypes) = do f <- newName "f"@@ -165,11 +184,11 @@ let pats = [varP f, conP name (map varP fieldNames)] constraintsAndFields = zipWith newField fieldNames fieldTypes newFields = map (snd <$>) constraintsAndFields- body = normalB $ appsE $ conE name : newFields+ body = normalB $ TH.appsE $ conE name : newFields newField :: Name -> BangType -> Q ([Type], Exp) newField x (_, fieldType) = genFmapField (varE f) fieldType (varE x) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause pats body []+ (,) constraints <$> TH.clause pats body [] genFmapClause (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -180,7 +199,7 @@ ((,) fieldName <$>) <$> genFmapField (varE f) fieldType (appE (varE fieldName) (varE x)) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP f, x `asP` recP name []] body []+ (,) constraints <$> TH.clause [varP f, x `TH.asP` TH.recP name []] body [] genFmapClause (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) = do Just (Deriving tyConName _tyVar) <- getQ putQ (Deriving tyConName tyVar)@@ -209,10 +228,10 @@ y <- newName "y" fieldNames2 <- replicateM (length fieldTypes) (newName "y") let pats = [varP f, conP name (map varP fieldNames1), varP y]- body = normalB $ appsE $ conE name : zipWith newField (zip fieldNames1 fieldNames2) fieldTypes+ body = normalB $ TH.appsE $ conE name : zipWith newField (zip fieldNames1 fieldNames2) fieldTypes newField :: (Name, Name) -> BangType -> Q Exp newField (x, y) (_, fieldType) = genLiftA2Field unsafely (varE f) fieldType (varE x) (varE y) id- clause pats body [valD (conP name $ map varP fieldNames2) (normalB $ varE y) []]+ TH.clause pats body [TH.valD (conP name $ map varP fieldNames2) (normalB $ varE y) []] genLiftA2Clause unsafely (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -220,9 +239,9 @@ let body = normalB $ recConE name $ map newNamedField fields newNamedField :: VarBangType -> Q (Name, Exp) newNamedField (fieldName, _, fieldType) =- fieldExp fieldName (genLiftA2Field unsafely (varE f) fieldType (getFieldOf x) (getFieldOf y) id)+ TH.fieldExp fieldName (genLiftA2Field unsafely (varE f) fieldType (getFieldOf x) (getFieldOf y) id) where getFieldOf = appE (varE fieldName) . varE- clause [varP f, x `asP` recP name [], varP y] body []+ TH.clause [varP f, x `TH.asP` TH.recP name [], varP y] body [] genLiftA2Clause unsafely (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) = do Just (Deriving tyConName _tyVar) <- getQ putQ (Deriving tyConName tyVar)@@ -255,11 +274,11 @@ fieldNames2 <- replicateM (length fieldTypes) (newName "y") fieldNames3 <- replicateM (length fieldTypes) (newName "z") let pats = [varP f, conP name (map varP fieldNames1), varP y, varP z]- body = normalB $ appsE $ conE name : zipWith newField (zip3 fieldNames1 fieldNames2 fieldNames3) fieldTypes+ body = normalB $ TH.appsE $ conE name : zipWith newField (zip3 fieldNames1 fieldNames2 fieldNames3) fieldTypes newField :: (Name, Name, Name) -> BangType -> Q Exp newField (x, y, z) (_, fieldType) = genLiftA3Field unsafely (varE f) fieldType (varE x) (varE y) (varE z) id- clause pats body [valD (conP name $ map varP fieldNames2) (normalB $ varE y) [],- valD (conP name $ map varP fieldNames3) (normalB $ varE z) []]+ TH.clause pats body [TH.valD (conP name $ map varP fieldNames2) (normalB $ varE y) [],+ TH.valD (conP name $ map varP fieldNames3) (normalB $ varE z) []] genLiftA3Clause unsafely (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -268,9 +287,10 @@ let body = normalB $ recConE name $ map newNamedField fields newNamedField :: VarBangType -> Q (Name, Exp) newNamedField (fieldName, _, fieldType) =- fieldExp fieldName (genLiftA3Field unsafely (varE f) fieldType (getFieldOf x) (getFieldOf y) (getFieldOf z) id)+ TH.fieldExp fieldName+ (genLiftA3Field unsafely (varE f) fieldType (getFieldOf x) (getFieldOf y) (getFieldOf z) id) where getFieldOf = appE (varE fieldName) . varE- clause [varP f, x `asP` recP name [], varP y, varP z] body []+ TH.clause [varP f, x `TH.asP` TH.recP name [], varP y, varP z] body [] genLiftA3Clause unsafely (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) = do Just (Deriving tyConName _tyVar) <- getQ putQ (Deriving tyConName tyVar)@@ -305,11 +325,11 @@ let pats = [conP name (map varP fieldNames1), varP rhsName] constraintsAndFields = zipWith newField (zip fieldNames1 fieldNames2) fieldTypes newFields = map (snd <$>) constraintsAndFields- body = normalB $ appsE $ conE name : newFields+ body = normalB $ TH.appsE $ conE name : newFields newField :: (Name, Name) -> BangType -> Q ([Type], Exp) newField (x, y) (_, fieldType) = genApField unsafely fieldType (varE x) (varE y) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause pats body [valD (conP name $ map varP fieldNames2) (normalB $ varE rhsName) []]+ (,) constraints <$> TH.clause pats body [TH.valD (conP name $ map varP fieldNames2) (normalB $ varE rhsName) []] genApClause unsafely (RecC name fields) = do x <- newName "x" y <- newName "y"@@ -320,7 +340,7 @@ ((,) fieldName <$>) <$> genApField unsafely fieldType (getFieldOf x) (getFieldOf y) id where getFieldOf = appE (varE fieldName) . varE constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [x `asP` recP name [], varP y] body []+ (,) constraints <$> TH.clause [x `TH.asP` TH.recP name [], varP y] body [] genApClause unsafely (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) = do Just (Deriving tyConName _tyVar) <- getQ putQ (Deriving tyConName tyVar)@@ -347,12 +367,12 @@ genPureClause :: Con -> Q ([Type], Clause) genPureClause (NormalC name fieldTypes) = do argName <- newName "f"- let body = normalB $ appsE $ conE name : ((snd <$>) <$> constraintsAndFields)+ let body = normalB $ TH.appsE $ conE name : ((snd <$>) <$> constraintsAndFields) constraintsAndFields = map newField fieldTypes newField :: BangType -> Q ([Type], Exp) newField (_, fieldType) = genPureField fieldType (varE argName) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP argName] body []+ (,) constraints <$> TH.clause [varP argName] body [] genPureClause (RecC name fields) = do argName <- newName "f" let body = normalB $ recConE name $ (snd <$>) <$> constraintsAndFields@@ -360,7 +380,7 @@ newNamedField :: VarBangType -> Q ([Type], (Name, Exp)) newNamedField (fieldName, _, fieldType) = ((,) fieldName <$>) <$> genPureField fieldType (varE argName) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP argName] body []+ (,) constraints <$> TH.clause [varP argName] body [] genPureField :: Type -> Q Exp -> (Q Exp -> Q Exp) -> Q ([Type], Exp) genPureField fieldType pureValue wrap = do@@ -385,7 +405,7 @@ newField :: Name -> BangType -> Q ([Type], Exp) newField x (_, fieldType) = genFoldMapField f fieldType (varE x) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause pats (normalB body) []+ (,) constraints <$> TH.clause pats (normalB body) [] genFoldMapClause (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -396,7 +416,7 @@ newField :: VarBangType -> Q ([Type], Exp) newField (fieldName, _, fieldType) = genFoldMapField f fieldType (appE (varE fieldName) (varE x)) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP f, x `asP` recP name []] (normalB body) []+ (,) constraints <$> TH.clause [varP f, x `TH.asP` TH.recP name []] (normalB body) [] genFoldMapClause (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) = do Just (Deriving tyConName _tyVar) <- getQ putQ (Deriving tyConName tyVar)@@ -421,7 +441,7 @@ genTraverseClause :: Con -> Q ([Type], Clause) genTraverseClause (NormalC name []) =- (,) [] <$> clause [wildP, conP name []] (normalB [| pure $(conE name) |]) []+ (,) [] <$> TH.clause [wildP, conP name []] (normalB [| pure $(conE name) |]) [] genTraverseClause (NormalC name fieldTypes) = do f <- newName "f" fieldNames <- replicateM (length fieldTypes) (newName "x")@@ -434,7 +454,7 @@ newField :: Name -> BangType -> Q ([Type], Exp) newField x (_, fieldType) = genTraverseField (varE f) fieldType (varE x) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause pats body []+ (,) constraints <$> TH.clause pats body [] genTraverseClause (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -445,7 +465,7 @@ newField :: VarBangType -> Q ([Type], Exp) newField (fieldName, _, fieldType) = genTraverseField (varE f) fieldType (appE (varE fieldName) (varE x)) id constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP f, x `asP` recP name []] body []+ (,) constraints <$> TH.clause [varP f, x `TH.asP` TH.recP name []] body [] genTraverseClause (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) = do Just (Deriving tyConName _tyVar) <- getQ putQ (Deriving tyConName tyVar)@@ -480,7 +500,7 @@ ((,) fieldName <$>) <$> (genCotraverseField ''Rank2.Distributive (varE 'Rank2.cotraverse) (varE withName) fieldType [| $(varE fieldName) <$> $(varE argName) |] id) constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP withName, varP argName] body []+ (,) constraints <$> TH.clause [varP withName, varP argName] body [] genCotraverseTraversableClause :: Con -> Q ([Type], Clause) genCotraverseTraversableClause (NormalC name []) = genCotraverseTraversableClause (RecC name [])@@ -495,8 +515,25 @@ (varE 'Rank2.cotraverseTraversable) (varE withName) fieldType [| $(varE fieldName) <$> $(varE argName) |] id) constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields- (,) constraints <$> clause [varP withName, varP argName] body []+ (,) constraints <$> TH.clause [varP withName, varP argName] body [] +genDeliverClause :: Con -> Q ([Type], Clause)+genDeliverClause (NormalC name []) = genDeliverClause (RecC name [])+genDeliverClause (RecC name fields) = do+ argName <- newName "f"+ let constraintsAndFields = map newNamedField fields+ body = normalB $ recConE name $ (snd <$>) <$> constraintsAndFields+ newNamedField :: VarBangType -> Q ([Type], (Name, Exp))+ newNamedField (fieldName, _, fieldType) =+ ((,) fieldName <$>)+ <$> (genDeliverField ''Rank2.Logistic [| contramap |] fieldType+ [| \set g-> $(TH.recUpdE [|g|] [(,) fieldName <$> [| Rank2.apply set $ $(varE fieldName) g |]]) |]+ [| \set g-> $(TH.recUpdE [|g|] [(,) fieldName <$> [| set $ $(varE fieldName) g |]]) |]+ (varE argName)+ id)+ constraints <- (concat . (fst <$>)) <$> sequence constraintsAndFields+ (,) constraints <$> TH.clause [varP argName] body []+ genCotraverseField :: Name -> Q Exp -> Q Exp -> Type -> Q Exp -> (Q Exp -> Q Exp) -> Q ([Type], Exp) genCotraverseField className method fun fieldType fieldAccess wrap = do Just (Deriving _ typeVar) <- getQ@@ -507,6 +544,18 @@ genCotraverseField className method fun t2 fieldAccess (wrap . appE (varE 'cotraverse)) SigT ty _kind -> genCotraverseField className method fun ty fieldAccess wrap ParensT ty -> genCotraverseField className method fun ty fieldAccess wrap++genDeliverField :: Name -> Q Exp -> Type -> Q Exp -> Q Exp -> Q Exp -> (Q Exp -> Q Exp) -> Q ([Type], Exp)+genDeliverField className fun fieldType fieldUpdate subRecordUpdate arg wrap = do+ Just (Deriving _ typeVar) <- getQ+ case fieldType of+ AppT ty _ | ty == VarT typeVar -> (,) [] <$> appE [|Compose|] (wrap fun `appE` fieldUpdate `appE` arg)+ AppT t1 t2 | t2 == VarT typeVar ->+ (,) (constrain className t1) <$> appE [| Rank2.deliver |] (wrap fun `appE` subRecordUpdate `appE` arg)+ AppT t1 t2 | t1 /= VarT typeVar ->+ genDeliverField className fun t2 fieldUpdate subRecordUpdate arg (wrap . appE (varE 'deliver))+ SigT ty _kind -> genDeliverField className fun ty fieldUpdate subRecordUpdate arg wrap+ ParensT ty -> genDeliverField className fun ty fieldUpdate subRecordUpdate arg wrap constrain :: Name -> Type -> [Type] constrain _ ConT{} = []