rank2classes 1.3.1.2 → 1.3.2.1
raw patch · 8 files changed
+97/−56 lines, 8 filesdep ~template-haskellbuild-type:Customsetup-changedPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: template-haskell
API changes (from Hackage documentation)
+ Rank2: ($) :: Arrow p q a -> p a -> q a
- Rank2: fmapTraverse :: (DistributiveTraversable f, Traversable g) => (forall a. g (t a) -> u a) -> g (f t) -> f u
+ Rank2: fmapTraverse :: (DistributiveTraversable g, Traversable f) => (forall a. f (t a) -> u a) -> f (g t) -> g u
- Rank2: infixr 0 ~>
+ Rank2: infixr 0 $
- Rank2: liftA2Traverse1 :: (Apply f, DistributiveTraversable f, Traversable g) => (forall a. g (t a) -> u a -> v a) -> g (f t) -> f u -> f v
+ Rank2: liftA2Traverse1 :: (Apply g, DistributiveTraversable g, Traversable f) => (forall a. f (t a) -> u a -> v a) -> f (g t) -> g u -> g v
- Rank2: liftA2Traverse2 :: (Apply f, DistributiveTraversable f, Traversable g) => (forall a. t a -> g (u a) -> v a) -> f t -> g (f u) -> f v
+ Rank2: liftA2Traverse2 :: (Apply g, DistributiveTraversable g, Traversable f) => (forall a. t a -> f (u a) -> v a) -> g t -> f (g u) -> g v
- Rank2: liftA2TraverseBoth :: (Apply f, DistributiveTraversable f, Traversable g1, Traversable g2) => (forall a. g1 (t a) -> g2 (u a) -> v a) -> g1 (f t) -> g2 (f u) -> f v
+ 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
Files
- CHANGELOG.md +8/−0
- README.md +12/−11
- Setup.hs +6/−2
- rank2classes.cabal +8/−3
- src/Rank2.hs +18/−15
- src/Rank2/TH.hs +29/−12
- test/Doctest.hs +4/−2
- test/MyModule.lhs +12/−11
CHANGELOG.md view
@@ -1,3 +1,11 @@+Version 1.3.2.1+---------------+* Incremented the upper bound of the template-haskell dependency++Version 1.3.2+---------------+* Exported the `$` synonym for `apply`+ Version 1.3.1.2 --------------- * Fixed doctest module name issue
README.md view
@@ -22,13 +22,14 @@ ~~~ The `Rank2` import will make available the following type classes:- * [Rank2.Functor](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Functor)- * [Rank2.Apply](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Apply)- * [Rank2.Applicative](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Applicative)- * [Rank2.Foldable](http://hackage.haskell.org/packages/archive/doc/html/Rank2.html#t:Foldable)- * [Rank2.Traversable](http://hackage.haskell.org/packages/archive/doc/html/Rank2.html#t:Traversable)- * [Rank2.Distributive](http://hackage.haskell.org/packages/archive/doc/html/Rank2.html#t:Distributive) + * [Rank2.Functor](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Functor)+ * [Rank2.Apply](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Apply)+ * [Rank2.Applicative](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Applicative)+ * [Rank2.Foldable](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Foldable)+ * [Rank2.Traversable](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Traversable)+ * [Rank2.Distributive](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Distributive)+ The methods of these type classes all have rank-2 types. The class instances are data types of kind `(k -> *) -> *`, one example of which would be a database record with different field types but all wrapped by the same type constructor:@@ -111,8 +112,8 @@ father= Rank2.Arrow (personByName db . getConst)} ~~~ -We can apply it using the [Rank2.<*>](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#v:-60--42--62-)-method of the [Rank2.Apply](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Apply) type class to a bunch+We can apply it using the [Rank2.<*>](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:-60--42--62-)+method of the [Rank2.Apply](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Apply) type class to a bunch of textual fields for `Person`, and get back either errors or proper field values: ~~~ {.haskell}@@ -121,7 +122,7 @@ ~~~ If there are no errors, we can get a fully verified record by applying-[Rank2.traverse](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#v:traverse) to the result:+[Rank2.traverse](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:traverse) to the result: ~~~ {.haskell} completeVerified :: PersonWithErrors -> Either String PersonVerified@@ -129,7 +130,7 @@ ~~~ or we can go in the opposite direction with-[Rank2.<$>](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#v:-60--36--62-):+[Rank2.<$>](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:-60--36--62-): ~~~ {.haskell} uncompleteVerified :: PersonVerified -> PersonWithErrors@@ -137,7 +138,7 @@ ~~~ If on the other hand there *are* errors, we can collect them using-[Rank2.foldMap](http://hackage.haskell.org/packages/rank2/doc/html#v:foldMap):+[Rank2.foldMap](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:foldMap): ~~~ {.haskell} verificationErrors :: PersonWithErrors -> [String]
Setup.hs view
@@ -1,2 +1,6 @@-import Distribution.Simple-main = defaultMain+module Main where++import Distribution.Extra.Doctest (defaultMainWithDoctests)++main :: IO ()+main = defaultMainWithDoctests "doctests"
rank2classes.cabal view
@@ -1,5 +1,5 @@ name: rank2classes-version: 1.3.1.2+version: 1.3.2.1 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@@ -14,13 +14,18 @@ maintainer: Mario Blažević <blamario@protonmail.com> copyright: (c) 2017 Mario Blažević category: Control, Data, Generics-build-type: Simple+build-type: Custom -- extra-source-files: cabal-version: >=1.10 extra-source-files: README.md, CHANGELOG.md, test/MyModule.lhs source-repository head type: git location: https://github.com/blamario/grampa+custom-setup+ setup-depends:+ base >= 4 && <5,+ Cabal,+ cabal-doctest >= 1 && <1.1 flag use-template-haskell description: Enable the compilation of the Rank2.TH module@@ -38,7 +43,7 @@ distributive < 0.7 if flag(use-template-haskell)- build-depends: template-haskell >= 2.11 && < 2.15+ build-depends: template-haskell >= 2.11 && < 2.16 exposed-modules: Rank2.TH test-suite doctests
src/Rank2.hs view
@@ -15,7 +15,7 @@ -- * Rank 2 data types Compose(..), Empty(..), Only(..), Flip(..), Identity(..), Product(..), Sum(..), Arrow(..), type (~>), -- * Method synonyms and helper functions- fst, snd, ap, fmap, liftA4, liftA5,+ ($), fst, snd, ap, fmap, liftA4, liftA5, fmapTraverse, liftA2Traverse1, liftA2Traverse2, liftA2TraverseBoth, distributeWith, distributeWithTraversable) where@@ -34,7 +34,7 @@ import Data.Proxy (Proxy(..)) import qualified GHC.Generics as Generics -import Prelude hiding (Foldable(..), Traversable(..), Functor(..), Applicative(..), (<$>), fst, snd)+import Prelude hiding (Foldable(..), Traversable(..), Functor(..), Applicative(..), ($), (<$>), fst, snd) -- | Helper function for accessing the first field of a 'Pair' fst :: Product g h p -> g p@@ -72,7 +72,10 @@ newtype Arrow p q a = Arrow{apply :: p a -> q a} type (~>) = Arrow+($) :: Arrow p q a -> p a -> q a+($) = apply infixr 0 ~>+infixr 0 $ -- | Subclass of 'Functor' halfway to 'Applicative', satisfying --@@ -134,22 +137,22 @@ distributeJoin = cotraverse Rank1.join -- | Like 'fmap', but traverses over its argument-fmapTraverse :: (DistributiveTraversable f, Rank1.Traversable g) => (forall a. g (t a) -> u a) -> g (f t) -> f u+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) -- | Like 'liftA2', but traverses over its first argument-liftA2Traverse1 :: (Apply f, DistributiveTraversable f, Rank1.Traversable g) =>- (forall a. g (t a) -> u a -> v a) -> g (f t) -> f u -> f v+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) -- | Like 'liftA2', but traverses over its second argument-liftA2Traverse2 :: (Apply f, DistributiveTraversable f, Rank1.Traversable g) => - (forall a. t a -> g (u a) -> v a) -> f t -> g (f u) -> f v+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) -- | Like 'liftA2', but traverses over both its arguments-liftA2TraverseBoth :: (Apply f, DistributiveTraversable f, Rank1.Traversable g1, Rank1.Traversable g2) =>- (forall a. g1 (t a) -> g2 (u a) -> v a) -> g1 (f t) -> g2 (f u) -> f v+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') @@ -410,10 +413,10 @@ instance DistributiveTraversable Proxy instance DistributiveTraversable (Only x) instance DistributiveTraversable g => DistributiveTraversable (Identity g) where- cotraverseTraversable w f = Identity (cotraverseTraversable w $ Rank1.fmap runIdentity f)+ cotraverseTraversable w f = Identity (cotraverseTraversable w (Rank1.fmap runIdentity 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)+ cotraverseTraversable w f = Pair (cotraverseTraversable w (Rank1.fmap fst f))+ (cotraverseTraversable w (Rank1.fmap snd f)) instance DistributiveTraversable f => DistributiveTraversable (Generics.M1 i c f) where cotraverseTraversable w f = Generics.M1 (cotraverseTraversable w (Rank1.fmap Generics.unM1 f))@@ -432,13 +435,13 @@ cotraverseTraversable _ f = coerce (Rank1.fold f) instance Distributive (Only x) where- cotraverse w f = Only (w $ Rank1.fmap fromOnly f)+ cotraverse w f = Only (w (Rank1.fmap fromOnly f)) instance Distributive g => Distributive (Identity g) where- cotraverse w f = Identity (cotraverse w $ Rank1.fmap runIdentity f)+ cotraverse w f = Identity (cotraverse w (Rank1.fmap runIdentity 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)+ 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)
src/Rank2/TH.hs view
@@ -197,14 +197,13 @@ genLiftA2Clause unsafely (NormalC name fieldTypes) = do f <- newName "f" fieldNames1 <- replicateM (length fieldTypes) (newName "x")+ y <- newName "y" fieldNames2 <- replicateM (length fieldTypes) (newName "y")- let pats = [varP f,- conP name (map varP fieldNames1),- tildeP (conP name $ map varP fieldNames2)]+ let pats = [varP f, conP name (map varP fieldNames1), varP y] body = normalB $ 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 []+ clause pats body [valD (conP name $ map varP fieldNames2) (normalB $ varE y) []] genLiftA2Clause unsafely (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -215,6 +214,15 @@ fieldExp fieldName (genLiftA2Field unsafely (varE f) fieldType (getFieldOf x) (getFieldOf y) id) where getFieldOf = appE (varE fieldName) . varE clause [varP f, bangP (varP x), varP y] body []+genLiftA2Clause unsafely (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) =+ do Just (Deriving tyConName _tyVar) <- getQ+ putQ (Deriving tyConName tyVar)+ genLiftA2Clause unsafely (NormalC name fieldTypes)+genLiftA2Clause unsafely (RecGadtC [name] fields _resultType@(AppT _ (VarT tyVar))) =+ do Just (Deriving tyConName _tyVar) <- getQ+ putQ (Deriving tyConName tyVar)+ genLiftA2Clause unsafely (RecC name fields)+genLiftA2Clause unsafely (ForallC _vars _cxt con) = genLiftA2Clause unsafely con genLiftA2Field :: Bool -> Q Exp -> Type -> Q Exp -> Q Exp -> (Q Exp -> Q Exp) -> Q Exp genLiftA2Field unsafely fun fieldType field1Access field2Access wrap = do@@ -233,16 +241,16 @@ genLiftA3Clause unsafely (NormalC name fieldTypes) = do f <- newName "f" fieldNames1 <- replicateM (length fieldTypes) (newName "x")+ y <- newName "y"+ z <- newName "z" fieldNames2 <- replicateM (length fieldTypes) (newName "y") fieldNames3 <- replicateM (length fieldTypes) (newName "z")- let pats = [varP f,- conP name (map varP fieldNames1),- tildeP (conP name $ map varP fieldNames2), - tildeP (conP name $ map varP fieldNames3)]+ 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 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 []+ clause pats body [valD (conP name $ map varP fieldNames2) (normalB $ varE y) [],+ valD (conP name $ map varP fieldNames3) (normalB $ varE z) []] genLiftA3Clause unsafely (RecC name fields) = do f <- newName "f" x <- newName "x"@@ -254,6 +262,15 @@ fieldExp fieldName (genLiftA3Field unsafely (varE f) fieldType (getFieldOf x) (getFieldOf y) (getFieldOf z) id) where getFieldOf = appE (varE fieldName) . varE clause [varP f, bangP (varP x), varP y, varP z] body []+genLiftA3Clause unsafely (GadtC [name] fieldTypes _resultType@(AppT _ (VarT tyVar))) =+ do Just (Deriving tyConName _tyVar) <- getQ+ putQ (Deriving tyConName tyVar)+ genLiftA3Clause unsafely (NormalC name fieldTypes)+genLiftA3Clause unsafely (RecGadtC [name] fields _resultType@(AppT _ (VarT tyVar))) =+ do Just (Deriving tyConName _tyVar) <- getQ+ putQ (Deriving tyConName tyVar)+ genLiftA3Clause unsafely (RecC name fields)+genLiftA3Clause unsafely (ForallC _vars _cxt con) = genLiftA3Clause unsafely con genLiftA3Field :: Bool -> Q Exp -> Type -> Q Exp -> Q Exp -> Q Exp -> (Q Exp -> Q Exp) -> Q Exp genLiftA3Field unsafely fun fieldType field1Access field2Access field3Access wrap = do@@ -275,15 +292,15 @@ genApClause unsafely (NormalC name fieldTypes) = do fieldNames1 <- replicateM (length fieldTypes) (newName "x") fieldNames2 <- replicateM (length fieldTypes) (newName "y")- let pats = [conP name (map varP fieldNames1),- tildeP (conP name $ map varP fieldNames2)]+ rhsName <- newName "rhs"+ 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 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 []+ (,) constraints <$> clause pats body [valD (conP name $ map varP fieldNames2) (normalB $ varE rhsName) []] genApClause unsafely (RecC name fields) = do x <- newName "x" y <- newName "y"
test/Doctest.hs view
@@ -1,3 +1,5 @@-import Test.DocTest+import Build_doctests (flags, pkgs, module_sources)+import Test.DocTest (doctest) -main = doctest ["-pgmL", "markdown-unlit", "-isrc", "test/MyModule.lhs"]+main = do doctest (flags ++ pkgs ++ module_sources)+ doctest (flags ++ pkgs ++ ["-pgmL", "markdown-unlit", "test/MyModule.lhs"])
test/MyModule.lhs view
@@ -22,13 +22,14 @@ ~~~ The `Rank2` import will make available the following type classes:- * [Rank2.Functor](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Functor)- * [Rank2.Apply](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Apply)- * [Rank2.Applicative](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Applicative)- * [Rank2.Foldable](http://hackage.haskell.org/packages/archive/doc/html/Rank2.html#t:Foldable)- * [Rank2.Traversable](http://hackage.haskell.org/packages/archive/doc/html/Rank2.html#t:Traversable)- * [Rank2.Distributive](http://hackage.haskell.org/packages/archive/doc/html/Rank2.html#t:Distributive) + * [Rank2.Functor](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Functor)+ * [Rank2.Apply](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Apply)+ * [Rank2.Applicative](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Applicative)+ * [Rank2.Foldable](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Foldable)+ * [Rank2.Traversable](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Traversable)+ * [Rank2.Distributive](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Distributive)+ The methods of these type classes all have rank-2 types. The class instances are data types of kind `(k -> *) -> *`, one example of which would be a database record with different field types but all wrapped by the same type constructor:@@ -111,8 +112,8 @@ father= Rank2.Arrow (personByName db . getConst)} ~~~ -We can apply it using the [Rank2.<*>](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#v:-60--42--62-)-method of the [Rank2.Apply](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#t:Apply) type class to a bunch+We can apply it using the [Rank2.<*>](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:-60--42--62-)+method of the [Rank2.Apply](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#t:Apply) type class to a bunch of textual fields for `Person`, and get back either errors or proper field values: ~~~ {.haskell}@@ -121,7 +122,7 @@ ~~~ If there are no errors, we can get a fully verified record by applying-[Rank2.traverse](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#v:traverse) to the result:+[Rank2.traverse](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:traverse) to the result: ~~~ {.haskell} completeVerified :: PersonWithErrors -> Either String PersonVerified@@ -129,7 +130,7 @@ ~~~ or we can go in the opposite direction with-[Rank2.<$>](http://hackage.haskell.org/packages/rank2/doc/html/Rank2.html#v:-60--36--62-):+[Rank2.<$>](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:-60--36--62-): ~~~ {.haskell} uncompleteVerified :: PersonVerified -> PersonWithErrors@@ -137,7 +138,7 @@ ~~~ If on the other hand there *are* errors, we can collect them using-[Rank2.foldMap](http://hackage.haskell.org/packages/rank2/doc/html#v:foldMap):+[Rank2.foldMap](http://hackage.haskell.org/package/rank2classes/docs/Rank2.html#v:foldMap): ~~~ {.haskell} verificationErrors :: PersonWithErrors -> [String]