packages feed

barbies 2.0.0.0 → 2.0.1.0

raw patch · 16 files changed

+605/−17 lines, 16 filesdep +distributivePVP ok

version bump matches the API change (PVP)

Dependencies added: distributive

API changes (from Hackage documentation)

+ Barbies.Bi: instance forall i (b :: i -> (* -> *) -> *). (forall (f :: i). Barbies.Internal.DistributiveB.DistributiveB (b f)) => Barbies.Internal.DistributiveT.DistributiveT (Barbies.Bi.Flip b)
+ Barbies.Bi: instance forall k (b :: (* -> *) -> k -> *) (f :: k). Barbies.Internal.DistributiveT.DistributiveT b => Barbies.Internal.DistributiveB.DistributiveB (Barbies.Bi.Flip b f)
+ Barbies.Internal: class (Functor f) => GDistributive (n :: Nat) f repbg repbfg
+ Barbies.Internal: gbdistributeDefault :: CanDeriveDistributiveB b f g => Functor f => f (b g) -> b (Compose f g)
+ Barbies.Internal: gdistribute :: GDistributive n f repbg repbfg => Proxy n -> f (repbg x) -> repbfg x
+ Barbies.Internal: type CanDeriveDistributiveB b f g = (GenericP 0 (b g), GenericP 0 (b (Compose f g)), GDistributive 0 f (RepP 0 (b g)) (RepP 0 (b (Compose f g))))
+ Barbies.Internal: type CanDeriveDistributiveT (t :: (Type -> Type) -> i -> Type) f g x = (GenericP 1 (t g x), GenericP 1 (t (Compose f g) x), GDistributive 1 f (RepP 1 (t g x)) (RepP 1 (t (Compose f g) x)))
+ Data.Functor.Barbie: bcotraverse :: (DistributiveB b, Functor f) => (forall a. f (g a) -> f a) -> f (b g) -> b f
+ Data.Functor.Barbie: bdecompose :: DistributiveB b => (a -> b Identity) -> b ((->) a)
+ Data.Functor.Barbie: bdistribute :: forall f g. (DistributiveB b, CanDeriveDistributiveB b f g) => Functor f => f (b g) -> b (Compose f g)
+ Data.Functor.Barbie: bdistribute' :: (DistributiveB b, Functor f) => f (b Identity) -> b f
+ Data.Functor.Barbie: brecompose :: FunctorB b => b ((->) a) -> a -> b Identity
+ Data.Functor.Barbie: class (FunctorB b) => DistributiveB (b :: (k -> Type) -> Type)
+ Data.Functor.Transformer: class FunctorT t => DistributiveT (t :: (Type -> Type) -> i -> Type)
+ Data.Functor.Transformer: tcotraverse :: (DistributiveT t, Functor f) => (forall a. f (g a) -> f a) -> f (t g x) -> t f x
+ Data.Functor.Transformer: tdecompose :: DistributiveT t => (a -> t Identity x) -> t ((->) a) x
+ Data.Functor.Transformer: tdistribute :: forall f g x. (DistributiveT t, CanDeriveDistributiveT t f g x) => f (t g x) -> t (Compose f g) x
+ Data.Functor.Transformer: tdistribute' :: (DistributiveT t, Functor f) => f (t Identity x) -> t f x
+ Data.Functor.Transformer: trecompose :: FunctorT t => t ((->) a) x -> a -> t Identity x

Files

ChangeLog.md view
@@ -1,5 +1,8 @@ # Changelog for barbies +## 2.0.1.0+  - Add the `DistributiveB` class (Gergő Érdi).+ ## 2.0.0.0   - Builds with ghc 8.8, but drops support for ghc 8.0 and 8.2   - Fix failure to derive `TraversableB` and `ConstraintsB` when using a type
barbies.cabal view
@@ -1,5 +1,5 @@ name:           barbies-version:        2.0.0.0+version:        2.0.1.0 synopsis:       Classes for working with types that can change clothes. description:    Types that are parametric on a functor are like Barbies that have an outfit for each role. This package provides the basic abstractions to work with them comfortably. category:       Data-structures@@ -43,6 +43,7 @@       Barbies.Generics.Applicative       Barbies.Generics.Bare       Barbies.Generics.Constraints+      Barbies.Generics.Distributive       Barbies.Generics.Functor       Barbies.Generics.Traversable @@ -55,6 +56,9 @@       Barbies.Internal.Containers       Barbies.Internal.Dicts +      Barbies.Internal.DistributiveB+      Barbies.Internal.DistributiveT+       Barbies.Internal.FunctorB       Barbies.Internal.FunctorT @@ -79,6 +83,7 @@    build-depends:       base >=4.11 && <5,+      distributive,       transformers    ghc-options: -Wall@@ -120,6 +125,7 @@       Spec.Applicative       Spec.Bare       Spec.Constraints+      Spec.Distributive       Spec.Functor       Spec.Traversable       Spec.Wrapper@@ -132,6 +138,7 @@   build-depends:       barbies     , base >=4.7 && <5+    , distributive     , QuickCheck     , tasty     , tasty-hunit
src/Barbies/Bi.hs view
@@ -161,6 +161,9 @@     = Flip (tmap h bfx)   {-# INLINE bmap #-} +instance DistributiveT b => DistributiveB (Flip b f) where+  bdistribute = Flip . tdistribute . fmap runFlip+  {-# INLINE bdistribute #-}  instance TraversableT b => TraversableB (Flip b f) where   btraverse h (Flip bfx)@@ -185,6 +188,10 @@   tmap h (Flip bxf)     = Flip (bmap h bxf)   {-# INLINE tmap #-}++instance (forall f. DistributiveB (b f)) => DistributiveT (Flip b) where+  tdistribute = Flip . bdistribute . fmap runFlip+  {-# INLINE tdistribute #-}  instance (forall f. TraversableB (b f)) => TraversableT (Flip b) where   ttraverse h (Flip bxf)
+ src/Barbies/Generics/Distributive.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE PolyKinds    #-}+{-# LANGUAGE TypeFamilies #-}+module Barbies.Generics.Distributive+  ( GDistributive(..)+  )++where++import Data.Generics.GenericN+import Data.Proxy (Proxy (..))++import Data.Functor.Compose   (Compose (..))+import Data.Distributive      (Distributive(..))++import GHC.TypeLits (Nat)++class (Functor f) => GDistributive (n :: Nat) f repbg repbfg where+  gdistribute :: Proxy n -> f (repbg x) -> repbfg x++-- ----------------------------------+-- Trivial cases+-- ----------------------------------++instance+  ( GDistributive n f bg bfg+  ) => GDistributive n f (M1 i c bg) (M1 i c bfg)+  where+  gdistribute pn = M1 . gdistribute pn . fmap unM1+  {-# INLINE gdistribute #-}+++instance+  ( Functor f+  ) => GDistributive n f U1 U1+  where+  gdistribute _ = const U1+  {-# INLINE gdistribute #-}+++fstF :: (l :*: r) a -> l a+fstF (x :*: _y) = x++sndF :: (l :*: r) a -> r a+sndF (_x :*: y) = y++instance+  ( GDistributive n f l l'+  , GDistributive n f r r'+  )+  => GDistributive n f (l :*: r) (l' :*: r')+  where+  gdistribute pn lr = gdistribute pn (fstF <$> lr) :*: gdistribute pn (sndF <$> lr)+  {-# INLINE gdistribute #-}+++-- ---------------------------------------------------------+-- The interesting cases.+-- There are more interesting cases for specific values of n+-- ---------------------------------------------------------++type P = Param++instance+  ( Functor f+  ) =>+  GDistributive n f (Rec (P n g a) (g a)) (Rec (P n (Compose f g) a) (Compose f g a))+  where+  gdistribute _ = Rec . K1 . Compose . id . fmap (unK1 . unRec)+  {-# INLINE gdistribute #-}++instance+  ( Functor f+  , Distributive h+  ) =>+  GDistributive n f (Rec (h (P n g a)) (h (g a))) (Rec (h (P n (Compose f g) a)) (h (Compose f g a)))+  where+  gdistribute _ = Rec . K1 . fmap Compose . distribute . fmap (unK1 . unRec)+  {-# INLINE gdistribute #-}
src/Barbies/Internal.hs view
@@ -5,15 +5,17 @@   , Internal.CanDeriveFunctorB   , Internal.CanDeriveFunctorT --     -- * Traversable   , Internal.gbtraverseDefault   , Generics.GTraversable(..)   , Internal.CanDeriveTraversableB   , Internal.CanDeriveTraversableT -+    -- * Distributive+  , Internal.gbdistributeDefault+  , Generics.GDistributive(..)+  , Internal.CanDeriveDistributiveB+  , Internal.CanDeriveDistributiveT      -- * Applicative   , Internal.gbpureDefault@@ -23,7 +25,6 @@   , Internal.CanDeriveApplicativeT  -     -- * Constraints   , Internal.gbaddDictsDefault   , Generics.GConstraints(..)@@ -54,6 +55,7 @@ import qualified Barbies.Generics.Applicative as Generics import qualified Barbies.Generics.Bare as Generics import qualified Barbies.Generics.Constraints as Generics+import qualified Barbies.Generics.Distributive as Generics import qualified Barbies.Generics.Functor as Generics import qualified Barbies.Generics.Traversable as Generics @@ -62,6 +64,8 @@ import qualified Barbies.Internal.BareB as Internal import qualified Barbies.Internal.ConstraintsB as Internal import qualified Barbies.Internal.ConstraintsT as Internal+import qualified Barbies.Internal.DistributiveB as Internal+import qualified Barbies.Internal.DistributiveT as Internal import qualified Barbies.Internal.FunctorB as Internal import qualified Barbies.Internal.FunctorT as Internal import qualified Barbies.Internal.TraversableB as Internal
+ src/Barbies/Internal/DistributiveB.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE PolyKinds    #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Barbies.Internal.DistributiveB+  ( DistributiveB(..)+  , bdistribute'+  , bcotraverse+  , bdecompose+  , brecompose+  , gbdistributeDefault+  , CanDeriveDistributiveB+  )++where++import Barbies.Internal.FunctorB (FunctorB(..))+import Barbies.Generics.Distributive (GDistributive(..))++import Data.Functor.Compose   (Compose (..))+import Data.Functor.Identity  (Identity (..))+import Data.Functor.Product   (Product (..))+import Data.Generics.GenericN+import Data.Proxy             (Proxy (..))+import Data.Distributive+import Data.Kind              (Type)++-- | A 'FunctorB' where the effects can be distributed to the fields:+--  `bdistribute` turns an effectful way of building a Barbie-type+--  into a pure Barbie-type with effectful ways of computing the+--  values of its fields.+--+--  This class is the categorical dual of `Barbies.Internal.TraversableB.TraversableB`,+--  with `bdistribute` the dual of `Barbies.Internal.TraversableB.bsequence`+--  and `bcotraverse` the dual of `Barbies.Internal.TraversableB.btraverse`. As such,+--  instances need to satisfy these laws:+--+-- @+-- 'bdistribute' . h = 'bmap' ('Compose' . h . 'getCompose') . 'bdistribute'    -- naturality+-- 'bdistribute' . 'Data.Functor.Identity' = 'bmap' ('Compose' . 'Data.Functor.Identity')                 -- identity+-- 'bdistribute' . 'Compose' = 'bmap' ('Compose' . 'Compose' . 'fmap' 'getCompose' . 'getCompose') . 'bdistribute' . 'fmap' 'bdistribute' -- composition+-- @+--+-- By specializing @f@ to @((->) a)@ and @g@ to 'Identity', we can define a function that+-- decomposes a function on distributive barbies into a collection of simpler functions:+--+-- @+-- 'bdecompose' :: 'DistributiveB' b => (a -> b 'Identity') -> b ((->) a)+-- 'bdecompose' = 'bmap' ('fmap' 'runIdentity' . 'getCompose') . 'bdistribute'+-- @+--+-- Lawful instances of the class can then be characterized as those that satisfy:+--+-- @+-- 'brecompose' . 'bdecompose' = 'id'+-- 'bdecompose' . 'brecompose' = 'id'+-- @+--+-- This means intuitively that instances need to have a fixed shape (i.e. no sum-types can be involved).+-- Typically, this means record types, as long as they don't contain fields where the functor argument is not applied.+--+--+-- There is a default implementation of 'bdistribute' based on+-- 'Generic'.  Intuitively, it works on product types where the shape+-- of a pure value is uniquely defined and every field is covered by+-- the argument @f@.+class (FunctorB b) => DistributiveB (b :: (k -> Type) -> Type) where+  bdistribute :: Functor f => f (b g) -> b (Compose f g)++  default bdistribute+    :: forall f g+    .  CanDeriveDistributiveB b f g+    => Functor f => f (b g) -> b (Compose f g)+  bdistribute = gbdistributeDefault+++-- | A version of `bdistribute` with @g@ specialized to `Identity`.+bdistribute' :: (DistributiveB b, Functor f) => f (b Identity) -> b f+bdistribute' = bmap (fmap runIdentity . getCompose) . bdistribute++-- | Dual of `Barbies.Internal.TraversableB.btraverse`+bcotraverse :: (DistributiveB b, Functor f) => (forall a . f (g a) -> f a) -> f (b g) -> b f+bcotraverse h = bmap (h . getCompose) . bdistribute++-- | Decompose a function returning a distributive barbie, into+--   a collection of simpler functions.+bdecompose :: DistributiveB b => (a -> b Identity) -> b ((->) a)+bdecompose = bdistribute'++-- | Recompose a decomposed function.+brecompose :: FunctorB b => b ((->) a) -> a -> b Identity+brecompose bfs = \a -> bmap (Identity . ($ a)) bfs++-- | @'CanDeriveDistributiveB' B f g@ is in practice a predicate about @B@ only.+--   Intuitively, it says the the following holds  for any arbitrary @f@:+--+--     * There is an instance of @'Generic' (B f)@.+--+--     * @(B f)@ has only one constructor, and doesn't contain "naked" fields+--       (that is, not covered by `f`).+--+--     * @B f@ can contain fields of type @b f@ as long as there exists a+--       @'DistributiveB' b@ instance. In particular, recursive usages of @B f@+--       are allowed.+--+--     * @B f@ can also contain usages of @b f@ under a @'Distributive' h@.+--       For example, one could use @a -> (B f)@ as a field of @B f@.+type CanDeriveDistributiveB b f g+  = ( GenericP 0 (b g)+    , GenericP 0 (b (Compose f g))+    , GDistributive 0 f (RepP 0 (b g)) (RepP 0 (b (Compose f g)))+    )++-- | Default implementation of 'bdistribute' based on 'Generic'.+gbdistributeDefault+  :: CanDeriveDistributiveB b f g+  => Functor f => f (b g) -> b (Compose f g)+gbdistributeDefault+  = toP (Proxy @0) . gdistribute (Proxy @0) . fmap (fromP (Proxy @0))+{-# INLINE gbdistributeDefault #-}++-- ------------------------------------------------------------+-- Generic derivation: Special cases for DistributiveB+-- -----------------------------------------------------------++type P = Param++instance+  ( Functor f+  , DistributiveB b+  ) => GDistributive 0 f (Rec (b' (P 0 g)) (b g)) (Rec (b' (P 0 (Compose f g))) (b (Compose f g)))+  where+  gdistribute _ = Rec . K1 . bdistribute . fmap (unK1 . unRec)+  {-# INLINE gdistribute #-}+++instance+  ( Functor f+  , Distributive h+  , DistributiveB b+  ) =>+  GDistributive n f (Rec (h (b (P n g))) (h (b g))) (Rec (h (b (P n (Compose f g)))) (h (b (Compose f g))))+  where+  gdistribute _ = Rec . K1 . fmap bdistribute . distribute . fmap (unK1 . unRec)+  {-# INLINE gdistribute #-}++-- --------------------------------+-- Instances for base types+-- --------------------------------++instance DistributiveB Proxy where+  bdistribute _ = Proxy+  {-# INLINE bdistribute #-}++fstF :: Product f g a -> f a+fstF (Pair x _y) = x++sndF :: Product f g a -> g a+sndF (Pair _x y) = y++instance (DistributiveB a, DistributiveB b) => DistributiveB (Product a b) where+  bdistribute xy = Pair (bdistribute $ fstF <$> xy) (bdistribute $ sndF <$> xy)+  {-# INLINE bdistribute #-}++instance (Distributive h, DistributiveB b) => DistributiveB (h `Compose` b) where+  bdistribute = Compose . fmap bdistribute . distribute . fmap getCompose+  {-# INLINE bdistribute #-}
+ src/Barbies/Internal/DistributiveT.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE PolyKinds    #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Barbies.Internal.DistributiveT+  ( DistributiveT(..)+  , tdistribute'+  , tcotraverse+  , tdecompose+  , trecompose+  , gtdistributeDefault+  , CanDeriveDistributiveT+  )++where++import Barbies.Generics.Distributive (GDistributive(..))+import Barbies.Internal.FunctorT (FunctorT (..))++import Control.Applicative.Backwards(Backwards (..))++import Control.Monad.Trans.Except(ExceptT(..), runExceptT)+import Control.Monad.Trans.Identity(IdentityT(..))+import Control.Monad.Trans.Maybe(MaybeT(..))+import Control.Monad.Trans.RWS.Lazy as Lazy (RWST(..))+import Control.Monad.Trans.RWS.Strict as Strict (RWST(..))+import Control.Monad.Trans.Reader(ReaderT(..))+import Control.Monad.Trans.State.Lazy as Lazy (StateT(..))+import Control.Monad.Trans.State.Strict as Strict (StateT(..))+import Control.Monad.Trans.Writer.Lazy as Lazy (WriterT(..))+import Control.Monad.Trans.Writer.Strict as Strict (WriterT(..))++import Data.Functor.Compose   (Compose (..))+import Data.Functor.Identity  (Identity (..))+import Data.Functor.Reverse   (Reverse (..))+import Data.Generics.GenericN+import Data.Proxy             (Proxy (..))+import Data.Distributive+import Data.Kind              (Type)++-- | A 'FunctorT' where the effects can be distributed to the fields:+--  `tdistribute` turns an effectful way of building a transformer-type+--  into a pure transformer-type with effectful ways of computing the+--  values of its fields.+--+--  This class is the categorical dual of `Barbies.Internal.TraversableT.TraversableT`,+--  with `tdistribute` the dual of `Barbies.Internal.TraversableT.tsequence`+--  and `tcotraverse` the dual of `Barbies.Internal.TraversableT.ttraverse`. As such,+--  instances need to satisfy these laws:+--+-- @+-- 'tdistribute' . h = 'tmap' ('Compose' . h . 'getCompose') . 'tdistribute'    -- naturality+-- 'tdistribute' . 'Data.Functor.Identity' = 'tmap' ('Compose' . 'Data.Functor.Identity')                 -- identity+-- 'tdistribute' . 'Compose' = 'fmap' ('Compose' . 'Compose' . 'fmap' 'getCompose' . 'getCompose') . 'tdistribute' . 'fmap' 'distribute' -- composition+-- @+--+-- By specializing @f@ to @((->) a)@ and @g@ to 'Identity', we can define a function that+-- decomposes a function on distributive transformers into a collection of simpler functions:+--+-- @+-- 'tdecompose' :: 'DistributiveT' b => (a -> b 'Identity') -> b ((->) a)+-- 'tdecompose' = 'tmap' ('fmap' 'runIdentity' . 'getCompose') . 'tdistribute'+-- @+--+-- Lawful instances of the class can then be characterized as those that satisfy:+--+-- @+-- 'trecompose' . 'tdecompose' = 'id'+-- 'tdecompose' . 'trecompose' = 'id'+-- @+--+-- This means intuitively that instances need to have a fixed shape (i.e. no sum-types can be involved).+-- Typically, this means record types, as long as they don't contain fields where the functor argument is not applied.+--+--+-- There is a default implementation of 'tdistribute' based on+-- 'Generic'.  Intuitively, it works on product types where the shape+-- of a pure value is uniquely defined and every field is covered by+-- the argument @f@.+class FunctorT t => DistributiveT (t :: (Type -> Type) -> i -> Type) where+  tdistribute :: Functor f => f (t g x) -> t (Compose f g) x++  default tdistribute+    :: forall f g x+    .  CanDeriveDistributiveT t f g x+    => f (t g x)+    -> t (Compose f g) x+  tdistribute = gtdistributeDefault++-- | A version of `tdistribute` with @g@ specialized to `Identity`.+tdistribute' :: (DistributiveT t, Functor f) => f (t Identity x) -> t f x+tdistribute' = tmap (fmap runIdentity . getCompose) . tdistribute++-- | Dual of `Barbies.Internal.TraversableT.ttraverse`+tcotraverse :: (DistributiveT t, Functor f) => (forall a . f (g a) -> f a) -> f (t g x) -> t f x+tcotraverse h = tmap (h . getCompose) . tdistribute++-- | Decompose a function returning a distributive transformer, into+--   a collection of simpler functions.+tdecompose :: DistributiveT t => (a -> t Identity x) -> t ((->) a) x+tdecompose = tdistribute'++-- | Recompose a decomposed function.+trecompose :: FunctorT t => t ((->) a) x -> a -> t Identity x+trecompose bfs = \a -> tmap (Identity . ($ a)) bfs++-- | @'CanDeriveDistributiveT' T f g x@ is in practice a predicate about @T@ only.+--   Intuitively, it says the the following holds  for any arbitrary @f@:+--+--     * There is an instance of @'Generic' (B f x)@.+--+--     * @(B f x)@ has only one constructor, and doesn't contain "naked" fields+--       (that is, not covered by `f`). In particular, @x@ needs to occur under @f@.+--+--     * @B f x@ can contain fields of type @b f y@ as long as there exists a+--       @'DistributiveT' b@ instance. In particular, recursive usages of @B f x@+--       are allowed.+--+--     * @B f x@ can also contain usages of @b f y@ under a @'Distributive' h@.+--       For example, one could use @a -> (B f x)@ as a field of @B f x@.+type CanDeriveDistributiveT (t :: (Type -> Type) -> i -> Type) f g x+  = ( GenericP 1 (t g x)+    , GenericP 1 (t (Compose f g) x)+    , GDistributive 1 f (RepP 1 (t g x)) (RepP 1 (t (Compose f g) x))+    )++-- | Default implementation of 'tdistribute' based on 'Generic'.+gtdistributeDefault+  :: CanDeriveDistributiveT t f g x+  => f (t g x)+  -> t (Compose f g) x+gtdistributeDefault = toP (Proxy @1) . gdistribute (Proxy @1) . fmap (fromP (Proxy @1))+{-# INLINE gtdistributeDefault #-}++------------------------------------------------------------+-- Generic derivation: Special cases for FunctorT+-- -----------------------------------------------------------++type P = Param++instance+  ( Functor f+  , DistributiveT t+  ) => GDistributive 1 f (Rec (t (P 1 g) x) (t g x)) (Rec (t (P 1 (Compose f g)) x) (t (Compose f g) x))+  where+  gdistribute _ = Rec . K1 . tdistribute . fmap (unK1 . unRec)+  {-# INLINE gdistribute #-}+++instance+  ( Functor f+  , Distributive h+  , DistributiveT t+  ) =>+  GDistributive 1 f (Rec (h (t (P 1 g) x)) (h (t g x))) (Rec (h (t (P 1 (Compose f g)) x)) (h (t (Compose f g) x)))+  where+  gdistribute _ = Rec . K1 . fmap tdistribute . distribute . fmap (unK1 . unRec)+  {-# INLINE gdistribute #-}++-- --------------------------------+-- Instances for base types+-- --------------------------------++instance Distributive f => DistributiveT (Compose f) where+  tdistribute = Compose . fmap Compose . distribute . fmap getCompose+  {-# INLINE tdistribute #-}++-- -- --------------------------------+-- -- Instances for transformers types+-- -- --------------------------------++instance DistributiveT Backwards where+  tdistribute = Backwards . Compose . fmap forwards+  {-# INLINE tdistribute #-}++instance DistributiveT Reverse where+  tdistribute = Reverse . Compose . fmap getReverse+  {-# INLINE tdistribute #-}++instance DistributiveT (ExceptT e) where+  tdistribute = ExceptT . Compose . fmap runExceptT+  {-# INLINE tdistribute #-}++instance DistributiveT IdentityT where+  tdistribute = IdentityT . Compose . fmap runIdentityT+  {-# INLINE tdistribute #-}++instance DistributiveT MaybeT where+  tdistribute = MaybeT . Compose . fmap runMaybeT+  {-# INLINE tdistribute #-}++instance DistributiveT (Lazy.RWST r w s) where+  tdistribute fh = Lazy.RWST $ \r s -> Compose $ fmap (\h -> Lazy.runRWST h r s) fh+  {-# INLINE tdistribute #-}++instance DistributiveT (Strict.RWST r w s) where+  tdistribute fh = Strict.RWST $ \r s -> Compose $ fmap (\h -> Strict.runRWST h r s) fh+  {-# INLINE tdistribute #-}++instance DistributiveT (ReaderT r) where+  tdistribute fh = ReaderT $ \r -> Compose $ fmap (\h -> runReaderT h r) fh+  {-# INLINE tdistribute #-}++instance DistributiveT (Lazy.StateT s) where+  tdistribute fh = Lazy.StateT $ \s -> Compose $ fmap (\h -> Lazy.runStateT h s) fh+  {-# INLINE tdistribute #-}++instance DistributiveT (Strict.StateT s) where+  tdistribute fh = Strict.StateT $ \s -> Compose $ fmap (\h -> Strict.runStateT h s) fh+  {-# INLINE tdistribute #-}++instance DistributiveT (Lazy.WriterT w) where+  tdistribute = Lazy.WriterT . Compose . fmap Lazy.runWriterT+  {-# INLINE tdistribute #-}++instance DistributiveT (Strict.WriterT w) where+  tdistribute = Strict.WriterT . Compose . fmap Strict.runWriterT+  {-# INLINE tdistribute #-}
src/Barbies/Internal/Trivial.hs view
@@ -9,6 +9,7 @@ import Barbies.Internal.ApplicativeB(ApplicativeB(..)) import Barbies.Internal.ConstraintsB(ConstraintsB(..)) import Barbies.Internal.FunctorB(FunctorB(..))+import Barbies.Internal.DistributiveB(DistributiveB(..)) import Barbies.Internal.TraversableB(TraversableB(..))  import Data.Data (Data(..))@@ -58,6 +59,7 @@   mappend = (<>)  instance FunctorB Unit+instance DistributiveB Unit instance TraversableB Unit instance ApplicativeB Unit instance ConstraintsB Unit
src/Data/Functor/Barbie.hs view
@@ -16,6 +16,13 @@   , Trav.bsequence   , Trav.bsequence' +    -- * Distributive+  , Distr.DistributiveB(bdistribute)+  , Distr.bdistribute'+  , Distr.bcotraverse+  , Distr.bdecompose+  , Distr.brecompose+     -- * Applicative   , Appl.ApplicativeB(bpure, bprod)     -- ** Utility functions@@ -67,6 +74,7 @@ import qualified Barbies.Internal.ApplicativeB as Appl import qualified Barbies.Internal.ConstraintsB as Cons import qualified Barbies.Internal.FunctorB as Func+import qualified Barbies.Internal.DistributiveB as Distr import qualified Barbies.Internal.TraversableB as Trav  import qualified Data.Generics.GenericN as GenericN
src/Data/Functor/Transformer.hs view
@@ -17,6 +17,13 @@   , Trav.tsequence   , Trav.tsequence' +    -- * Distributive+  , Dist.DistributiveT(tdistribute)+  , Dist.tdistribute'+  , Dist.tcotraverse+  , Dist.tdecompose+  , Dist.trecompose+     -- * Applicative   , Appl.ApplicativeT(tpure, tprod)     -- ** Utility functions@@ -45,6 +52,7 @@  import qualified Barbies.Internal.ApplicativeT as Appl import qualified Barbies.Internal.ConstraintsT as Cons+import qualified Barbies.Internal.DistributiveT as Dist import qualified Barbies.Internal.FunctorT as Func import qualified Barbies.Internal.MonadT as Mon import qualified Barbies.Internal.TraversableT as Trav
test/Clothes.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveFunctor #-} module Clothes  where@@ -16,7 +16,7 @@ data UnitF a = UnitF deriving(Eq, Show, Typeable)  data F a = F [a]-  deriving(Eq, Show, Typeable)+  deriving(Eq, Show, Typeable, Functor)  instance Eq1 F where   liftEq eq (F as) (F bs) = liftEq eq as bs@@ -26,7 +26,7 @@     = showsUnaryWith (liftShowsPrec sp sl) "F" d as  data G a = NoG | G1 a | Gn [a]-  deriving(Eq, Show, Typeable)+  deriving(Eq, Show, Typeable, Functor)  instance Eq1 G where   liftEq _  NoG     NoG     = True@@ -43,7 +43,7 @@     Gn as -> showsUnaryWith (liftShowsPrec sp sl) "Gn" d as  data H a = NoH1 | NoH2 | H1 [a] | H2 [a] | H3 [a]-  deriving(Eq, Show, Typeable)+  deriving(Eq, Show, Typeable, Functor)  instance Show1 H where   liftShowsPrec sp sl d = \case
test/Spec.hs view
@@ -6,6 +6,7 @@ import qualified Spec.Functor as Functor import qualified Spec.Applicative as Applicative import qualified Spec.Traversable as Traversable+import qualified Spec.Distributive as Distributive import qualified Spec.Wrapper as Wrapper  import TestBarbies@@ -69,6 +70,29 @@             , Functor.laws @(Flip Bi.NestedF ())             , Functor.laws @(Flip Bi.Nested2F ())             , Functor.laws @(Flip Bi.NestedB Maybe)+            ]++        , testGroup "Distributive Laws"+            [ Distributive.laws @Record0+            , Distributive.laws @Record1++            , Distributive.laws @Record1S+            , Distributive.laws @Record3S++            , Distributive.laws @(Record1W Covered)+            , Distributive.laws @(Record3W Covered)++            , Distributive.laws @CompositeRecord++            , Distributive.laws @(Record1WS Covered)+            , Distributive.laws @(Record3WS Covered)++            , Distributive.laws @(CompositeRecordW Covered)++            , Distributive.laws @(Flip Bi.Record0 ())+            , Distributive.laws @(Flip Bi.Record1 ())+            , Distributive.laws @(Flip Bi.Record1S ())+            , Distributive.laws @(Flip Bi.Record3S ())             ]          , testGroup "Traversable Laws"
+ test/Spec/Distributive.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+module Spec.Distributive ( laws )++where++import Clothes (F, G, H, GH(..), NatTransf(..))++import Data.Functor.Identity (Identity(..))+import Data.Functor.Compose (Compose (..))++import Data.Functor.Barbie (FunctorB(..), DistributiveB(..))++import Data.Typeable (Typeable, typeRep, Proxy(..))++import Test.Tasty(testGroup, TestTree)+import Test.Tasty.QuickCheck(Arbitrary(..), testProperty, (===))++type IsDomain a = (Arbitrary a, Show a)+type IsRange a = (Eq a, Show a)++laws+  :: forall b+  . ( DistributiveB b+    , IsDomain (b F)+    , IsRange (b (Compose H F))+    , IsRange (b (Compose Identity F))+    , IsRange (b (Compose (Compose H G) F))+    , Typeable b+    )+  => TestTree+laws+  = testGroup (show (typeRep (Proxy :: Proxy b)))+      [ testProperty "naturality" $ \(GH (NatTransf h)) (fb :: G (b F)) ->+           bdistribute (h fb) === bmap (Compose . h . getCompose) (bdistribute fb)+      , testProperty "identity" $ \(b :: b F) ->+           bdistribute (Identity b) === bmap (Compose . Identity) b+      , testProperty "composition" $ \(fb :: H (G (b F))) ->+           bdistribute (Compose fb) === bmap (Compose . Compose . fmap getCompose . getCompose) (bdistribute . fmap bdistribute $ fb)+      ]
test/TestBarbies.hs view
@@ -31,6 +31,7 @@  import qualified Barbies import Data.Functor.Barbie+import Data.Distributive  import Data.Typeable import GHC.Generics@@ -48,6 +49,7 @@     )  instance FunctorB Record0+instance DistributiveB Record0 instance TraversableB Record0 instance ApplicativeB Record0 instance ConstraintsB Record0@@ -61,6 +63,7 @@   instance FunctorB Record1+instance DistributiveB Record1 instance TraversableB Record1 instance ApplicativeB Record1 instance ConstraintsB Record1@@ -78,6 +81,7 @@   instance FunctorB Record1S+instance DistributiveB Record1S instance TraversableB Record1S instance ApplicativeB Record1S instance ConstraintsB Record1S@@ -121,6 +125,7 @@   instance FunctorB Record3S+instance DistributiveB Record3S instance TraversableB Record3S instance ApplicativeB Record3S instance ConstraintsB Record3S@@ -179,12 +184,12 @@   = CompositeRecord       { crec_f1 :: f Int       , crec_F2 :: f Bool-      , crec_f3 :: Record3 f       , crec_f4 :: Record1 f       }   deriving (Generic, Typeable)  instance FunctorB CompositeRecord+instance DistributiveB CompositeRecord instance TraversableB CompositeRecord instance ApplicativeB CompositeRecord instance ConstraintsB CompositeRecord@@ -194,7 +199,7 @@  instance AllBF Arbitrary f CompositeRecord => Arbitrary (CompositeRecord f) where   arbitrary-    = CompositeRecord <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary+    = CompositeRecord <$> arbitrary <*> arbitrary <*> arbitrary  data SumRec f   = SumRec_0@@ -222,6 +227,7 @@   deriving (Generic, Typeable)  instance FunctorB InfRec+instance DistributiveB InfRec instance TraversableB InfRec instance ApplicativeB InfRec instance ConstraintsB InfRec@@ -281,6 +287,7 @@   deriving (Generic, Typeable)  instance FunctorB b => FunctorB (ParB b)+instance DistributiveB b => DistributiveB (ParB b) instance TraversableB b => TraversableB (ParB b) instance ApplicativeB b => ApplicativeB (ParB b) instance ConstraintsB b => ConstraintsB (ParB b)@@ -290,6 +297,7 @@   deriving (Generic, Typeable)  instance (Functor h, FunctorB b) => FunctorB (ParBH h b)+instance (Distributive h, DistributiveB b) => DistributiveB (ParBH h b) instance (Traversable h, TraversableB b) => TraversableB (ParBH h b) instance (Applicative h, ApplicativeB b) => ApplicativeB (ParBH h b) 
test/TestBarbiesW.hs view
@@ -40,6 +40,7 @@  instance FunctorB (Record1W Bare) instance FunctorB (Record1W Covered)+instance DistributiveB (Record1W Covered) instance TraversableB (Record1W Covered) instance ApplicativeB (Record1W Covered) instance ConstraintsB (Record1W Bare)@@ -63,6 +64,7 @@  instance FunctorB (Record1WS Bare) instance FunctorB (Record1WS Covered)+instance DistributiveB (Record1WS Covered) instance TraversableB (Record1WS Covered) instance ApplicativeB (Record1WS Covered) instance ConstraintsB (Record1WS Bare)@@ -89,6 +91,7 @@  instance FunctorB (Record3W Bare) instance FunctorB (Record3W Covered)+instance DistributiveB (Record3W Covered) instance TraversableB (Record3W Bare) instance TraversableB (Record3W Covered) instance ApplicativeB (Record3W Covered)@@ -117,6 +120,7 @@  instance FunctorB (Record3WS Bare) instance FunctorB (Record3WS Covered)+instance DistributiveB (Record3WS Covered) instance TraversableB (Record3WS Covered) instance ApplicativeB (Record3WS Covered) instance ConstraintsB (Record3WS Bare)@@ -179,6 +183,7 @@  instance FunctorB (CompositeRecordW Bare) instance FunctorB (CompositeRecordW Covered)+instance DistributiveB (CompositeRecordW Covered) instance TraversableB (CompositeRecordW Covered) instance ApplicativeB (CompositeRecordW Covered) instance ConstraintsB (CompositeRecordW Bare)@@ -228,6 +233,7 @@  instance FunctorB (InfRecW Bare) instance FunctorB (InfRecW Covered)+instance DistributiveB (InfRecW Covered) instance TraversableB (InfRecW Covered) instance ApplicativeB (InfRecW Covered) instance ConstraintsB (InfRecW Bare)@@ -333,6 +339,7 @@  instance FunctorB (ParXW a Bare) instance FunctorB (ParXW a Covered)+instance DistributiveB (ParXW a Covered) instance TraversableB (ParXW a Covered) instance ApplicativeB (ParXW a Covered) instance ConstraintsB (ParXW a Covered)
test/TestBiBarbies.hs view
@@ -33,6 +33,7 @@ where  import Barbies+import Data.Distributive import qualified TestBarbies  import Data.Typeable@@ -54,6 +55,7 @@     )  instance FunctorT Record0+instance DistributiveT Record0 instance ApplicativeT Record0 instance TraversableT Record0 instance ConstraintsT Record0@@ -67,6 +69,7 @@   instance FunctorT Record1+instance DistributiveT Record1 instance ApplicativeT Record1 instance TraversableT Record1 instance ConstraintsT Record1@@ -84,6 +87,7 @@   instance FunctorT Record1S+instance DistributiveT Record1S instance ApplicativeT Record1S instance TraversableT Record1S instance ConstraintsT Record1S@@ -126,6 +130,7 @@   instance FunctorT Record3S+instance DistributiveT Record3S instance ApplicativeT Record3S instance TraversableT Record3S instance ConstraintsT Record3S@@ -287,6 +292,7 @@   deriving (Generic, Typeable)  instance FunctorT b => FunctorT (ParB b)+instance DistributiveT b => DistributiveT (ParB b) instance ApplicativeT b => ApplicativeT (ParB b) instance TraversableT b => TraversableT (ParB b) instance ConstraintsT b => ConstraintsT (ParB b)@@ -296,6 +302,7 @@   deriving (Generic, Typeable)  instance (Functor h, FunctorT b) => FunctorT (ParBH h b)+instance (Distributive h, DistributiveT b) => DistributiveT (ParBH h b) instance (Applicative h, ApplicativeT b) => ApplicativeT (ParBH h b) instance (Traversable h, TraversableT b) => TraversableT (ParBH h b) @@ -337,28 +344,29 @@ -- Actual bi-barbies ----------------------------------------------------- -type Record3' = TestBarbies.Record3+type Record1' = TestBarbies.Record1  data NestedB f g   = NestedB       { nb_1 :: g Int       , nb_2 :: f (g Bool)-      , nb_3 :: f (Record3' g)-      , nb_4 :: Record3' g+      , nb_3 :: f (Record1' g)+      , nb_4 :: Record1' g       }   deriving (Generic, Typeable)  instance FunctorT NestedB instance TraversableT NestedB instance Functor f => FunctorB (NestedB f)+instance Distributive f => DistributiveB (NestedB f) instance Applicative f => ApplicativeB (NestedB f) instance Traversable f => TraversableB (NestedB f)  -deriving instance (Show (f (g Bool)), AllBF Show g Record3', Show (f (Record3' g))) => Show (NestedB f g)-deriving instance (Eq (f (g Bool)), AllBF Eq g Record3', Eq (f (Record3' g))) => Eq (NestedB f g)+deriving instance (Show (f (g Bool)), AllBF Show g Record1', Show (f (Record1' g))) => Show (NestedB f g)+deriving instance (Eq (f (g Bool)), AllBF Eq g Record1', Eq (f (Record1' g))) => Eq (NestedB f g)  -instance (Arbitrary (f (g Bool)), AllBF Arbitrary g Record3', Arbitrary (f (Record3' g))) => Arbitrary (NestedB f g) where+instance (Arbitrary (f (g Bool)), AllBF Arbitrary g Record1', Arbitrary (f (Record1' g))) => Arbitrary (NestedB f g) where   arbitrary     = NestedB <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary