rank2classes 1.3.2.1 → 1.4
raw patch · 6 files changed
+79/−24 lines, 6 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Rank2: infixr 9 `Compose`
- Rank2: newtype Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1) :: forall k k1. () => k -> Type -> k1 -> k -> k1 -> Type
+ Rank2: infixl 4 <*>
+ Rank2: instance forall k (g :: (k -> *) -> *) (p :: * -> *). (Rank2.Applicative g, GHC.Base.Applicative p) => Rank2.Applicative (Rank2.Compose g p)
+ Rank2: instance forall k (g :: (k -> *) -> *) (p :: * -> *). (Rank2.Apply g, GHC.Base.Applicative p) => Rank2.Apply (Rank2.Compose g p)
+ 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 -> *) -> *) (p :: * -> *). (Rank2.DistributiveTraversable g, Data.Distributive.Distributive p) => Rank2.DistributiveTraversable (Rank2.Compose g p)
+ Rank2: instance forall k (g :: (k -> *) -> *) (p :: * -> *). (Rank2.Foldable g, Data.Foldable.Foldable p) => Rank2.Foldable (Rank2.Compose g p)
+ Rank2: instance forall k (g :: (k -> *) -> *) (p :: * -> *). (Rank2.Functor g, GHC.Base.Functor p) => Rank2.Functor (Rank2.Compose g p)
+ Rank2: instance forall k (g :: (k -> *) -> *) (p :: * -> *). (Rank2.Traversable g, Data.Traversable.Traversable p) => Rank2.Traversable (Rank2.Compose g p)
+ Rank2: instance forall k k1 (g :: (k1 -> *) -> *) (p :: k -> *) (q :: k1 -> k). GHC.Classes.Eq (g (Data.Functor.Compose.Compose p q)) => GHC.Classes.Eq (Rank2.Compose g p q)
+ Rank2: instance forall k k1 (g :: (k1 -> *) -> *) (p :: k -> *) (q :: k1 -> k). GHC.Classes.Ord (g (Data.Functor.Compose.Compose p q)) => GHC.Classes.Ord (Rank2.Compose g p q)
+ Rank2: instance forall k k1 (g :: (k1 -> *) -> *) (p :: k -> *) (q :: k1 -> k). GHC.Show.Show (g (Data.Functor.Compose.Compose p q)) => GHC.Show.Show (Rank2.Compose g p q)
+ Rank2: newtype Compose g p q
- Rank2: Compose :: f (g a) -> Compose
+ Rank2: Compose :: g (Compose p q) -> Compose g p q
- Rank2: [getCompose] :: Compose -> f (g a)
+ Rank2: [getCompose] :: Compose g p q -> g (Compose p q)
Files
- CHANGELOG.md +6/−0
- README.md +2/−1
- rank2classes.cabal +2/−2
- src/Rank2.hs +66/−20
- src/Rank2/TH.hs +1/−0
- test/MyModule.lhs +2/−1
CHANGELOG.md view
@@ -1,3 +1,9 @@+Version 1.4+---------------+* Added Rank2.Compose :: ((* -> *) -> *) -> (* -> *) -> ((* -> *) -> *)+* Matched the precedence of <$> and <*> operators with Prelude+* Relaxed the lower bound of base dependency to 4.10+ Version 1.3.2.1 --------------- * Incremented the upper bound of the template-haskell dependency
README.md view
@@ -208,4 +208,5 @@ ~~~ Grammars are another use case that is almost, but not quite, completely unlike database records. See-[grammatical-parsers](https://github.com/blamario/grampa/tree/master/grammatical-parsers) about that.+[grammatical-parsers](https://github.com/blamario/grampa/tree/master/grammatical-parsers) or+[construct](https://hackage.haskell.org/package/construct) for examples.
rank2classes.cabal view
@@ -1,5 +1,5 @@ name: rank2classes-version: 1.3.2.1+version: 1.4 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@@ -38,7 +38,7 @@ default-language: Haskell2010 -- other-modules: ghc-options: -Wall- build-depends: base >=4.12 && <5,+ build-depends: base >=4.10 && <5, transformers >= 0.5 && < 0.6, distributive < 0.7
src/Rank2.hs view
@@ -6,7 +6,7 @@ -- @Rank2.@ prefix and a twist that their methods operate on a heterogenous collection. The same property is shared by -- the two less standard classes 'Apply' and 'Distributive'. {-# LANGUAGE DefaultSignatures, InstanceSigs, KindSignatures, PolyKinds, Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables, TypeOperators #-}+{-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-} {-# LANGUAGE EmptyCase #-} module Rank2 ( -- * Rank 2 classes@@ -24,10 +24,11 @@ import qualified Control.Monad as Rank1 import qualified Data.Foldable as Rank1 import qualified Data.Traversable as Rank1+import qualified Data.Functor.Compose as Rank1+import qualified Data.Distributive as Rank1 import Data.Coerce (coerce) import Data.Semigroup (Semigroup(..)) import Data.Monoid (Monoid(..))-import Data.Functor.Compose (Compose(Compose, getCompose)) import Data.Functor.Const (Const(..)) import Data.Functor.Product (Product(Pair)) import Data.Functor.Sum (Sum(InL, InR))@@ -50,6 +51,7 @@ -- > (p . q) <$> g == p <$> (q <$> g) class Functor g where (<$>) :: (forall a. p a -> q a) -> g p -> g q+infixl 4 <$> -- | Alphabetical synonym for '<$>' fmap :: Functor g => (forall a. p a -> q a) -> g p -> g q@@ -64,9 +66,9 @@ class (Functor g, Foldable g) => Traversable g where {-# MINIMAL traverse | sequence #-} traverse :: Rank1.Applicative m => (forall a. p a -> m (q a)) -> g p -> m (g q)- sequence :: Rank1.Applicative m => g (Compose m p) -> m (g p)- traverse f = sequence . fmap (Compose . f)- sequence = traverse getCompose+ 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}@@ -92,6 +94,7 @@ (<*>) = liftA2 apply liftA2 f g h = (Arrow . f) <$> g <*> h liftA3 f g h i = liftA2 (\p q-> Arrow (f p q)) g h <*> i+infixl 4 <*> liftA4 :: Apply g => (forall a. p a -> q a -> r a -> s a -> t a) -> g p -> g q -> g r -> g s -> g t liftA4 f g h i j = liftA3 (\p q r-> Arrow (f p q r)) g h i <*> j@@ -110,23 +113,23 @@ -- | 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 (Compose f1 f2)- distribute :: Rank1.Functor f1 => f1 (g f2) -> g (Compose f1 f2)+ 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) -- | 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 Compose- cotraverse f = (fmap (f . getCompose)) . distribute+ distribute = cotraverse Rank1.Compose+ 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- collectTraversable :: Rank1.Traversable f1 => (a -> g f2) -> f1 a -> g (Compose f1 f2) - distributeTraversable :: Rank1.Traversable f1 => f1 (g f2) -> g (Compose f1 f2)+ 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 collectTraversable f = distributeTraversable . Rank1.fmap f- distributeTraversable = cotraverseTraversable Compose+ distributeTraversable = cotraverseTraversable Rank1.Compose default cotraverseTraversable :: (Rank1.Traversable m, Distributive g) => (forall a. m (p a) -> q a) -> m (g p) -> g q@@ -138,23 +141,23 @@ -- | Like 'fmap', but traverses over its argument fmapTraverse :: (DistributiveTraversable g, Rank1.Traversable f) => (forall a. f (t a) -> u a) -> f (g t) -> g u-fmapTraverse f x = fmap (f . getCompose) (distributeTraversable x)+fmapTraverse f x = fmap (f . Rank1.getCompose) (distributeTraversable x) -- | Like 'liftA2', but traverses over its first argument liftA2Traverse1 :: (Apply g, DistributiveTraversable g, Rank1.Traversable f) => (forall a. f (t a) -> u a -> v a) -> f (g t) -> g u -> g v-liftA2Traverse1 f x = liftA2 (f . getCompose) (distributeTraversable x)+liftA2Traverse1 f x = liftA2 (f . Rank1.getCompose) (distributeTraversable x) -- | Like 'liftA2', but traverses over its second argument liftA2Traverse2 :: (Apply g, DistributiveTraversable g, Rank1.Traversable f) => (forall a. t a -> f (u a) -> v a) -> g t -> f (g u) -> g v-liftA2Traverse2 f x y = liftA2 (\x' y' -> f x' (getCompose y')) x (distributeTraversable y)+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) => (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 (getCompose x') (getCompose y')+ where applyCompose x' y' = f (Rank1.getCompose x') (Rank1.getCompose y') {-# DEPRECATED distributeWith "Use cotraverse instead." #-} -- | Synonym for 'cotraverse'@@ -167,7 +170,7 @@ (forall a. m (p a) -> q a) -> m (g p) -> g q distributeWithTraversable = cotraverseTraversable --- | A rank-2 equivalent of '()', a zero-element tuple+-- | A rank-2 equivalent of @()@, a zero-element tuple data Empty f = Empty deriving (Eq, Ord, Show) -- | A rank-2 tuple of only one element@@ -176,6 +179,13 @@ -- | Equivalent of 'Data.Functor.Identity' for rank 2 data types newtype Identity g f = Identity {runIdentity :: g f} deriving (Eq, Ord, Show) +-- | Equivalent of 'Data.Functor.Compose' for rank 2 data types+newtype Compose g p q = Compose {getCompose :: g (Rank1.Compose p q)}++deriving instance Eq (g (Rank1.Compose p q)) => Eq (Compose g p q)+deriving instance Ord (g (Rank1.Compose p q)) => Ord (Compose g p q)+deriving instance Show (g (Rank1.Compose p q)) => Show (Compose g p q)+ -- | A nested parametric type represented as a rank-2 type newtype Flip g a f = Flip {unFlip :: g (f a)} deriving (Eq, Ord, Show) @@ -216,6 +226,12 @@ instance Functor g => Functor (Identity g) where f <$> Identity g = Identity (f <$> g) +instance (Functor g, Rank1.Functor p) => Functor (Compose g p) where+ (<$>) :: forall q r. (forall a. q a -> r a) -> Compose g p q -> Compose g p r+ f <$> Compose g = Compose (f' <$> g)+ where f' :: forall a. Rank1.Compose p q a -> Rank1.Compose p r a+ f' (Rank1.Compose q) = Rank1.Compose (f Rank1.<$> q)+ instance (Functor g, Functor h) => Functor (Product g h) where f <$> Pair a b = Pair (f <$> a) (f <$> b) @@ -246,7 +262,7 @@ f <$> Generics.R1 x = Generics.R1 (f <$> x) instance (Functor f, Functor g) => Functor ((Generics.:*:) f g) where- f <$> (x Generics.:*: y) = f <$> x Generics.:*: f <$> y+ f <$> (x Generics.:*: y) = (f <$> x) Generics.:*: (f <$> y) instance Foldable Empty where foldMap _ _ = mempty@@ -263,6 +279,9 @@ instance Foldable g => Foldable (Identity g) where foldMap f (Identity g) = foldMap f g +instance (Foldable g, Rank1.Foldable p) => Foldable (Compose g p) where+ foldMap f (Compose g) = foldMap (Rank1.foldMap f . Rank1.getCompose) g+ instance (Foldable g, Foldable h) => Foldable (Product g h) where foldMap f (Pair g h) = foldMap f g `mappend` foldMap f h @@ -290,7 +309,7 @@ foldMap f (Generics.R1 x) = foldMap f x instance (Foldable f, Foldable g) => Foldable ((Generics.:*:) f g) where- foldMap f (x Generics.:*: y) = foldMap f x <> foldMap f y+ foldMap f (x Generics.:*: y) = foldMap f x `mappend` foldMap f y instance Traversable Empty where traverse _ _ = Rank1.pure Empty@@ -307,6 +326,12 @@ instance Traversable g => Traversable (Identity g) where traverse f (Identity g) = Identity Rank1.<$> traverse f g +instance (Traversable g, Rank1.Traversable p) => Traversable (Compose g p) where+ traverse :: forall m q r. Rank1.Applicative m => (forall a. q a -> m (r a)) -> Compose g p q -> m (Compose g p r)+ traverse f (Compose g) = Compose Rank1.<$> traverse f' g+ where f' :: forall a. Rank1.Compose p q a -> m (Rank1.Compose p r a)+ f' (Rank1.Compose q) = Rank1.Compose Rank1.<$> Rank1.traverse f q+ instance (Traversable g, Traversable h) => Traversable (Product g h) where traverse f (Pair g h) = Rank1.liftA2 Pair (traverse f g) (traverse f h) @@ -356,6 +381,16 @@ Identity g <*> Identity h = Identity (g <*> h) liftA2 f (Identity g) (Identity h) = Identity (liftA2 f g h) +instance (Apply g, Rank1.Applicative p) => Apply (Compose g p) where+ (<*>) :: forall q r. Compose g p (q ~> r) -> Compose g p q -> Compose g p r+ liftA2 :: forall q r s. (forall a. q a -> r a -> s a) -> Compose g p q -> Compose g p r -> Compose g p s+ Compose g <*> Compose h = Compose (liftA2 f' g h)+ where f' :: forall a. Rank1.Compose p (q ~> r) a -> Rank1.Compose p q a -> Rank1.Compose p r a+ f' (Rank1.Compose f) (Rank1.Compose q) = Rank1.Compose (Rank1.liftA2 apply f q)+ liftA2 f (Compose g) (Compose h) = Compose (liftA2 f' g h)+ where f' :: forall a. Rank1.Compose p q a -> Rank1.Compose p r a -> Rank1.Compose p s a+ f' (Rank1.Compose q) (Rank1.Compose r) = Rank1.Compose (Rank1.liftA2 f q r)+ instance (Apply g, Apply h) => Apply (Product g h) where Pair gf hf <*> ~(Pair gx hx) = Pair (gf <*> gx) (hf <*> hx) liftA2 f (Pair g1 h1) ~(Pair g2 h2) = Pair (liftA2 f g1 g2) (liftA2 f h1 h2)@@ -394,6 +429,9 @@ instance Applicative g => Applicative (Identity g) where pure f = Identity (pure f) +instance (Applicative g, Rank1.Applicative p) => Applicative (Compose g p) where+ pure f = Compose (pure (Rank1.Compose (Rank1.pure f)))+ instance (Applicative g, Applicative h) => Applicative (Product g h) where pure f = Pair (pure f) (pure f) @@ -414,6 +452,10 @@ instance DistributiveTraversable (Only x) instance DistributiveTraversable g => DistributiveTraversable (Identity g) where cotraverseTraversable w f = Identity (cotraverseTraversable w (Rank1.fmap runIdentity f))+instance (DistributiveTraversable g, Rank1.Distributive p) => DistributiveTraversable (Compose g p) where+ cotraverseTraversable w f = Compose (cotraverseTraversable+ (Rank1.Compose . Rank1.fmap w . Rank1.distribute . Rank1.fmap Rank1.getCompose)+ (Rank1.fmap getCompose f)) instance (DistributiveTraversable g, DistributiveTraversable h) => DistributiveTraversable (Product g h) where cotraverseTraversable w f = Pair (cotraverseTraversable w (Rank1.fmap fst f)) (cotraverseTraversable w (Rank1.fmap snd f))@@ -440,11 +482,15 @@ instance Distributive g => Distributive (Identity g) where cotraverse w f = Identity (cotraverse w (Rank1.fmap runIdentity f)) +instance (Distributive g, Rank1.Distributive p) => Distributive (Compose g p) where+ cotraverse w f = Compose (cotraverse (Rank1.Compose . Rank1.fmap w . Rank1.distribute . Rank1.fmap Rank1.getCompose)+ (Rank1.fmap getCompose f))+ instance (Distributive g, Distributive h) => Distributive (Product g h) where cotraverse w f = Pair (cotraverse w (Rank1.fmap fst f)) (cotraverse w (Rank1.fmap snd f)) instance Monoid c => DistributiveTraversable (Generics.K1 i c) where- cotraverseTraversable _ f = coerce (Rank1.fold f)+ cotraverseTraversable _ f = coerce (Rank1.foldMap Generics.unK1 f) instance Distributive f => Distributive (Generics.M1 i c f) where cotraverse w f = Generics.M1 (cotraverse w (Rank1.fmap Generics.unM1 f))
src/Rank2/TH.hs view
@@ -46,6 +46,7 @@ pragInlD '(Rank2.<*>) Inlinable FunLike AllPhases, pragInlD 'Rank2.liftA2 Inlinable FunLike AllPhases]] +-- | This function always succeeds, but the methods it generates may be partial. Use with care. unsafeDeriveApply :: Name -> Q [Dec] unsafeDeriveApply ty = do (instanceType, cs) <- reifyConstructors ''Rank2.Apply ty
test/MyModule.lhs view
@@ -208,4 +208,5 @@ ~~~ Grammars are another use case that is almost, but not quite, completely unlike database records. See-[grammatical-parsers](https://github.com/blamario/grampa/tree/master/grammatical-parsers) about that.+[grammatical-parsers](https://github.com/blamario/grampa/tree/master/grammatical-parsers) or+[construct](https://hackage.haskell.org/package/construct) for examples.