packages feed

functor-combinators 0.3.2.0 → 0.3.3.0

raw patch · 9 files changed

+229/−223 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Functor.Combinator: divideN :: Divisible f => NP f as -> f (NP I as)
- Data.Functor.Combinator: divideNRec :: Divisible f => Rec f as -> f (XRec Identity as)
- Data.Functor.Combinator: diviseN :: Divise f => NP f (a : as) -> f (NP I (a : as))
- Data.Functor.Combinator: diviseNRec :: Divise f => Rec f (a : as) -> f (XRec Identity (a : as))
- Data.Functor.Contravariant.Divisible.Free: [Conquer] :: Div f a
- Data.Functor.Contravariant.Divisible.Free: [Div1] :: (a -> (b, c)) -> f b -> Div f c -> Div1 f a
- Data.Functor.Contravariant.Divisible.Free: [Divide] :: (a -> (b, c)) -> f b -> Div f c -> Div f a
- Data.Functor.Contravariant.Divisible.Free: data Div :: (Type -> Type) -> Type -> Type
- Data.Functor.Contravariant.Divisible.Free: data Div1 :: (Type -> Type) -> Type -> Type
+ Control.Applicative.ListF: instance Data.Functor.Contravariant.Conclude.Conclude f => Data.Functor.Contravariant.Conclude.Conclude (Control.Applicative.ListF.MaybeF f)
+ Control.Applicative.ListF: instance Data.Functor.Contravariant.Contravariant f => Data.Functor.Contravariant.Contravariant (Control.Applicative.ListF.MaybeF f)
+ Control.Applicative.ListF: instance Data.Functor.Contravariant.Contravariant f => Data.Functor.Contravariant.Divise.Divise (Control.Applicative.ListF.MaybeF f)
+ Control.Applicative.ListF: instance Data.Functor.Contravariant.Contravariant f => Data.Functor.Contravariant.Divisible.Divisible (Control.Applicative.ListF.MaybeF f)
+ Control.Applicative.ListF: instance Data.Functor.Contravariant.Decide.Decide f => Data.Functor.Contravariant.Decide.Decide (Control.Applicative.ListF.MaybeF f)
+ Control.Applicative.ListF: instance Data.Functor.Contravariant.Divisible.Decidable f => Data.Functor.Contravariant.Divisible.Decidable (Control.Applicative.ListF.MaybeF f)
+ Control.Applicative.ListF: instance Data.Functor.Invariant.Invariant f => Data.Functor.Invariant.Invariant (Control.Applicative.ListF.MaybeF f)
+ Data.Functor.Combinator: dsum :: (Foldable t, Divisible f) => t (f a) -> f a
+ Data.Functor.Combinator: dsum1 :: (Foldable1 t, Divise f) => t (f a) -> f a
+ Data.Functor.Combinator: injectContramap :: (Inject t, Contravariant f) => (a -> b) -> f b -> t f a
+ Data.Functor.Combinator: injectMap :: (Inject t, Functor f) => (a -> b) -> f a -> t f b
+ Data.Functor.Contravariant.Divise: (<:>) :: Divise f => f a -> f a -> f a
+ Data.Functor.Contravariant.Divise: dsum1 :: (Foldable1 t, Divise f) => t (f a) -> f a
+ Data.Functor.Contravariant.Divisible.Free: Div :: [Coyoneda f a] -> Div f a
+ Data.Functor.Contravariant.Divisible.Free: Div1 :: NonEmpty (Coyoneda f a) -> Div1 f a
+ Data.Functor.Contravariant.Divisible.Free: [unDiv1] :: Div1 f a -> NonEmpty (Coyoneda f a)
+ Data.Functor.Contravariant.Divisible.Free: [unDiv] :: Div f a -> [Coyoneda f a]
+ Data.Functor.Contravariant.Divisible.Free: newtype Div f a
+ Data.Functor.Contravariant.Divisible.Free: newtype Div1 f a
+ Data.Functor.Contravariant.Divisible.Free: pattern Conquer :: Div f a
+ Data.Functor.Contravariant.Divisible.Free: pattern Div1_ :: (a -> (b, c)) -> f b -> Div f c -> Div1 f a
+ Data.Functor.Contravariant.Divisible.Free: pattern Divide :: (a -> (b, c)) -> f b -> Div f c -> Div f a
+ Data.HFunctor: injectContramap :: (Inject t, Contravariant f) => (a -> b) -> f b -> t f a
+ Data.HFunctor: injectMap :: (Inject t, Functor f) => (a -> b) -> f a -> t f b
- Data.Functor.Contravariant.Divisible.Free: toDiv :: Div1 f a -> Div f a
+ Data.Functor.Contravariant.Divisible.Free: toDiv :: Div1 f ~> Div f

Files

CHANGELOG.md view
@@ -1,6 +1,31 @@ Changelog ========= +Version 0.3.3.0+---------------++*August 11, 2020*++<https://github.com/mstksg/functor-combinators/releases/tag/v0.3.3.0>++*   *Control.Applicative.ListF*: Missing contravariant instances added for+    `MaybeF`.+*   *Data.HFunctor*: Add `injectMap` and `injectContramap`, two small utility+    functions that represent common patterns in injection and mapping.+*   *Data.Functor.Combinator*: Replace `divideN` and related functions with+    `dsum` and `dsum1`, which is an altogether cleaner interface that doesn't+    require heterogenous lists.  A part of a larger project on cleaning up+    `Divisible` tools.+*   *Data.Functor.Contravariant.Divise*: Add useful utility functions `dsum`+    and `<:>`, which makes the type of `divise` closer to that of `<|>` and+    `asum`.+*   *Data.Functor.Contravariant.Divisible.Free*: Implement `Div` in terms of a+    list, instead of the mirrored `Ap`.  Should make it much easier to use,+    although a less-than-ideal `Coyoneda` is required to keep it compatible+    with the contravariant `Day` in *kan-extensions*.  Added patterns to+    recover the original interface.++ Version 0.3.2.0 --------------- 
functor-combinators.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 7c970e85e59e29124e48109889879a7e961d4b9b33326f5a8eaeffcc117f1ced+-- hash: c410805d5e691767b93cffa33046c105029599cb34a0389840cbf00a85077538  name:           functor-combinators-version:        0.3.2.0+version:        0.3.3.0 synopsis:       Tools for functor combinator-based program design description:    Tools for working with /functor combinators/: types that take functors (or                 other indexed types) and returns a new functor that "enhances" or "mixes"
src/Control/Applicative/ListF.hs view
@@ -245,6 +245,40 @@     empty = zero     (<|>) = (<!>) +-- | @since 0.3.3.0+instance Contravariant f => Contravariant (MaybeF f) where+    contramap f (MaybeF x) = MaybeF $ (fmap . contramap) f x++-- | @since 0.3.3.0+instance Invariant f => Invariant (MaybeF f) where+    invmap f g (MaybeF x) = MaybeF $ fmap (invmap f g) x++-- | @since 0.3.3.0+instance Contravariant f => Divise (MaybeF f) where+    divise f (MaybeF x) (MaybeF y) = MaybeF $+          (fmap . contramap) (fst . f) x+      <|> (fmap . contramap) (snd . f) y++-- | @since 0.3.3.0+instance Contravariant f => Divisible (MaybeF f) where+    divide  = divise+    conquer = MaybeF Nothing++-- | @since 0.3.3.0+instance Decide f => Decide (MaybeF f) where+    decide f (MaybeF x) (MaybeF y) = MaybeF $+        liftA2 (decide f) x y++-- | @since 0.3.3.0+instance Conclude f => Conclude (MaybeF f) where+    conclude f = MaybeF (Just (conclude f))++-- | @since 0.3.3.0+instance Decidable f => Decidable (MaybeF f) where+    choose f (MaybeF x) (MaybeF y) = MaybeF $+        liftA2 (choose f) x y+    lose f = MaybeF (Just (lose f))+ -- | Picks the first 'Just'. instance Semigroup (MaybeF f a) where     MaybeF xs <> MaybeF ys = MaybeF (xs <!> ys)
src/Data/Functor/Combinator.hs view
@@ -46,6 +46,7 @@   , iget, icollect, icollect1   , iapply, ifanout, ifanout1   , getI, collectI+  , injectMap, injectContramap   , AltConst(..)   -- ** Multi-Functors   -- | Classes that deal with two-functor combinators, that "mix" two@@ -109,12 +110,10 @@   , generalize   , absorb   -- ** Divisible-  , divideN-  , diviseN+  , dsum+  , dsum1   , concludeN   , decideN-  , divideNRec-  , diviseNRec   ) where  import           Control.Alternative.Free@@ -147,112 +146,27 @@ import           Data.HFunctor.Internal import           Data.HFunctor.Interpret import           GHC.Generics--import qualified Data.SOP           as SOP-import qualified Data.Vinyl         as V-import qualified Data.Vinyl.Functor as V+import qualified Data.SOP                             as SOP  --- | Convenient helper function to build up a 'Divisible' by providing--- each component of it.  This makes it much easier to build up longer--- chains as opposed to nested calls to 'divide' and manually peeling off--- tuples one-by-one.------ For example, if you had a data type------ @--- data MyType = MT Int Bool String--- @------ and a contravariant consumer @Builder@ (representing, say, a way to--- serialize an item, where @intBuilder :: Builder Int@ is a serializer of--- 'Int's), then you could assemble a serializer a @MyType@ using:------ @--- contramap (\(MyType x y z) -> I x :* I y :* I z :* Nil) $---   divideN $ intBuilderj---          :* boolBuilder---          :* stringBuilder---          :* Nil--- @------ Some notes on usefulness depending on how many components you have:------ *    If you have 0 components, use 'conquer'.--- *    If you have 1 component, use 'inject' directly.--- *    If you have 2 components, use 'divide' directly.--- *    If you have 3 or more components, these combinators may be useful;---      otherwise you'd need to manually peel off tuples one-by-one.------ @since 0.3.0.0-divideN-    :: Divisible f-    => SOP.NP f as-    -> f (SOP.NP SOP.I as)-divideN = \case-    SOP.Nil     -> conquer-    x SOP.:* xs -> divide-      (\case SOP.I y SOP.:* ys -> (y, ys))-      x-      (divideN xs)---- | A version of 'divideN' defined to work with 'V.XRec', which can--- syntactically cleaner because you don't have to manually wrap/unwrap--- 'SOP.I's.------ Using the example for 'divideN':+-- | Convenient helper function to build up a 'Divisible' by splitting+-- input across many different @f a@s.  Most useful when used alongside+-- 'contramap': -- -- @--- data MyType = MT Int Bool String------ contramap (\(MyType x y z) -> x ::& y ::& z ::& Nil) $---   divideNRec $ intBuilderj---             :& boolBuilder---             :& stringBuilder---             :& RNil+-- dsum [+--     contramap get1 x+--   , contramap get2 y+--   , contramap get3 z+--   ] -- @ ----- @since 0.3.0.0-divideNRec-    :: Divisible f-    => V.Rec f as-    -> f (V.XRec V.Identity as)-divideNRec = \case-    V.RNil    -> conquer-    x V.:& xs -> divide-      (\case z V.::& zs -> (z, zs))-      x-      (divideNRec xs)---- | A version of 'divideNRec' that works for non-empty records, and so only--- requires a 'Divise' constraint.------ @since 0.3.0.0-diviseNRec-    :: Divise f-    => V.Rec f (a ': as)-    -> f (V.XRec V.Identity (a ': as))-diviseNRec = \case-    x V.:& xs -> case xs of-      V.RNil   -> contramap (\case z V.::& _ -> z) x-      _ V.:& _ -> divise-        (\case z V.::& zs -> (z,zs))-        x-        (diviseNRec xs)---- | A version of 'divideN' that works for non-empty 'SOP.NP', and so only--- requires a 'Divise' constraint.-diviseN-    :: Divise f-    => SOP.NP f (a ': as)-    -> f (SOP.NP SOP.I (a ': as))-diviseN = \case-    x SOP.:* xs -> case xs of-      SOP.Nil    -> contramap (SOP.unI . SOP.hd) x-      _ SOP.:* _ -> divise-        (\case SOP.I z SOP.:* zs -> (z, zs))-        x-        (diviseN xs)+-- @since 0.3.3.0+dsum+    :: (Foldable t, Divisible f)+    => t (f a)+    -> f a+dsum = foldr (divide (\x -> (x,x))) conquer  -- | Convenient helper function to build up a 'Conclude' by providing -- each component of it.  This makes it much easier to build up longer
src/Data/Functor/Contravariant/Divise.hs view
@@ -19,6 +19,8 @@ module Data.Functor.Contravariant.Divise (     Divise(..)   , divised+  , (<:>)+  , dsum1   , WrappedDivisible(..)   ) where @@ -37,6 +39,7 @@ import qualified Control.Monad.Trans.State.Strict as Strict import qualified Control.Monad.Trans.Writer.Lazy as Lazy import qualified Control.Monad.Trans.Writer.Strict as Strict+import qualified Data.Semigroup.Foldable as F1  import Data.Functor.Apply import Data.Functor.Compose@@ -104,6 +107,26 @@ -- @ divised :: Divise f => f a -> f b -> f (a, b) divised = divise id++-- | The Contravariant version of '<|>': split the same input over two+-- different consumers.+(<:>) :: Divise f => f a -> f a -> f a+x <:> y = divise (\r -> (r,r)) x y++-- | Convenient helper function to build up a 'Divise' by splitting+-- input across many different @f a@s.  Most useful when used alongside+-- 'contramap':+--+-- @+-- dsum1 $ contramap get1 x+--    :| [ contramap get2 y+--       , contramap get3 z+--       ]+-- @+--+-- @since 0.3.3.0+dsum1 :: (F1.Foldable1 t, Divise f) => t (f a) -> f a+dsum1 = foldr1 (<:>) . F1.toNonEmpty  -- | Wrap a 'Divisible' to be used as a member of 'Divise' newtype WrappedDivisible f a = WrapDivisible { unwrapDivisible :: f a }
src/Data/Functor/Contravariant/Divisible/Free.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DerivingVia #-}+ -- | -- Module      : Data.Functor.Contravariant.Divisible.Free -- Copyright   : (c) Justin Le 2019@@ -12,10 +14,10 @@ -- -- @since 0.3.0.0 module Data.Functor.Contravariant.Divisible.Free (-    Div(..)+    Div(.., Conquer, Divide)   , hoistDiv, liftDiv, runDiv   , divListF, listFDiv-  , Div1(..)+  , Div1(.., Div1_)   , hoistDiv1, liftDiv1, toDiv, runDiv1   , div1NonEmptyF, nonEmptyFDiv1   , Dec(..)@@ -28,8 +30,10 @@ import           Control.Natural import           Data.Bifunctor import           Data.Bifunctor.Assoc+import           Data.Foldable import           Data.Functor.Contravariant import           Data.Functor.Contravariant.Conclude+import           Data.Functor.Contravariant.Coyoneda import           Data.Functor.Contravariant.Decide import           Data.Functor.Contravariant.Divise import           Data.Functor.Contravariant.Divisible@@ -37,161 +41,148 @@ import           Data.HFunctor import           Data.HFunctor.Interpret import           Data.Kind-import           Data.List import           Data.List.NonEmpty                   (NonEmpty(..)) import           Data.Void+import qualified Control.Monad.Trans.Compose          as CT+import qualified Data.Functor.Contravariant.Day       as CD  -- | The free 'Divisible'.  Used to sequence multiple contravariant -- consumers, splitting out the input across all consumers. ----- Note that @'Div' f@ is essentially @'ListF'--- ('Data.Functor.Contravariant.Coyoneda' f)@, or just @'ListF' f@ in the--- case that @f@ is already contravariant.  However, this is left in here--- because it can be more convenient to use if you are working with an--- intermediate @f@ that isn't 'Contravariant'.-data Div :: (Type -> Type) -> Type -> Type where-    Conquer :: Div f a-    Divide  :: (a -> (b, c)) -> f b -> Div f c -> Div f a+-- This type is essentially 'ListF'; the only reason why it has to exist+-- separately outside of 'ListF' is because the current typeclass hierarchy+-- isn't compatible with both the covariant 'Interpret' instance (requiring+-- 'Plus') and the contravariant 'Interpret' instance (requiring+-- 'Divisible').+--+-- The wrapping in 'Coyoneda' is also to provide a usable+-- 'Data.HBifunctor.Associative.Associative' instance for the contravariant+-- 'CD.Day'.+newtype Div f a = Div { unDiv :: [Coyoneda f a] }+  deriving (Contravariant, Divise, Divisible) via (ListF (Coyoneda f))+  deriving (HFunctor, Inject) via (CT.ComposeT ListF Coyoneda) -instance Contravariant (Div f) where-    contramap :: forall a b. (a -> b) -> Div f b -> Div f a-    contramap f = \case-      Conquer       -> Conquer-      Divide g x xs -> Divide (g . f) x xs instance Invariant (Div f) where     invmap _ = contramap -instance Divise (Div f) where-    divise f = \case-      Conquer       -> contramap (snd . f)-      Divide g x xs -> Divide (assoc . first g . f) x-                     . divise id xs-instance Divisible (Div f) where-    conquer  = Conquer-    divide   = divise+-- | Pattern matching on an empty 'Div'.+--+-- Before v0.3.3.0, this used to be the concrete constructor of 'Div'.+-- After, it is now an abstract pattern.+pattern Conquer :: Div f a+pattern Conquer = Div [] +-- | Pattern matching on a non-empty 'Div', exposing the raw @f@ instead of+-- having it wrapped in a 'Coyoneda'.  This is the analogue of+-- 'Control.Applicative.Free.Pure' and essentially treats the "cons" of the+-- 'Div' as a contravariant day convolution.+--+-- Before v0.3.3.0, this used to be the concrete constructor of 'Div'.+-- After, it is now an abstract pattern.+pattern Divide :: (a -> (b, c)) -> f b -> Div f c -> Div f a+pattern Divide f x xs <- (divDay_ -> Just (CD.Day x xs f))+  where+    Divide f x (Div xs) = Div $ Coyoneda (fst . f) x : (map . contramap) (snd . f) xs+{-# COMPLETE Conquer, Divide #-}++divDay_ :: Div f a -> Maybe (CD.Day f (Div f) a)+divDay_ (Div []) = Nothing+divDay_ (Div (Coyoneda f x : xs)) = Just $ CD.Day x (Div xs) (\y -> (f y, y))+ -- | 'Div' is isomorphic to 'ListF' for contravariant @f@.  This witnesses -- one way of that isomorphism.------ Be aware that this is essentially O(n^2). divListF :: forall f. Contravariant f => Div f ~> ListF f-divListF = ListF . unfoldr go-  where-    go = \case-      Conquer       -> Nothing-      Divide f x xs -> Just ( contramap (fst . f) x-                            , contramap (snd . f) xs-                            )+divListF = ListF . map lowerCoyoneda . unDiv  -- | 'Div' is isomorphic to 'ListF' for contravariant @f@.  This witnesses -- one way of that isomorphism.------ This direction is O(n), unlike 'divListF'. listFDiv :: ListF f ~> Div f-listFDiv = foldr (Divide (\y -> (y,y))) Conquer . runListF+listFDiv = Div . map liftCoyoneda . runListF  -- | Map over the undering context in a 'Div'. hoistDiv :: forall f g. (f ~> g) -> Div f ~> Div g-hoistDiv f = go-  where-    go :: Div f ~> Div g-    go = \case-      Conquer       -> Conquer-      Divide g x xs -> Divide g (f x) (go xs)+hoistDiv = hmap  -- | Inject a single action in @f@ into a @'Div' f@. liftDiv :: f ~> Div f-liftDiv x = Divide (,()) x Conquer+liftDiv = inject  -- | Interpret a 'Div' into a context @g@, provided @g@ is 'Divisible'. runDiv :: forall f g. Divisible g => (f ~> g) -> Div f ~> g-runDiv f = go+runDiv f = foldr go conquer . unDiv   where-    go :: Div f ~> g-    go = \case-      Conquer       -> conquer-      Divide g x xs -> divide g (f x) (go xs)+    go (Coyoneda g x) = divide (\y -> (y,y)) (contramap g (f x)) -instance HFunctor Div where-    hmap = hoistDiv-instance Inject Div where-    inject = liftDiv instance Divisible f => Interpret Div f where     interpret = runDiv  -- | The free 'Divise': a non-empty version of 'Div'. ----- Note that @'Div1' f@ is essentially @'NonEmptyF'--- ('Data.Functor.Contravariant.Coyoneda' f)@, or just @'NonEmptyF' f@ in the--- case that @f@ is already contravariant.  However, it can be more--- convenient to use if you are working with an intermediate @f@ that isn't--- 'Contravariant'.-data Div1 :: (Type -> Type) -> Type -> Type where-    Div1 :: (a -> (b, c)) -> f b -> Div f c -> Div1 f a+-- This type is essentially 'NonEmptyF'; the only reason why it has to exist+-- separately outside of 'NonEmptyF' is because the current typeclass+-- hierarchy isn't compatible with both the covariant 'Interpret' instance+-- (requiring 'Plus') and the contravariant 'Interpret' instance (requiring+-- 'Divisible').+--+-- The wrapping in 'Coyoneda' is also to provide a usable+-- 'Data.HBifunctor.Associative.Associative' instance for the contravariant+-- 'CD.Day'.+newtype Div1 f a = Div1 { unDiv1 :: NonEmpty (Coyoneda f a) }+  deriving (Contravariant, Divise) via (NonEmptyF (Coyoneda f))+  deriving (HFunctor, Inject) via (CT.ComposeT NonEmptyF Coyoneda) -instance Contravariant (Div1 f) where-    contramap f (Div1 g x xs) = Div1 (g . f) x xs instance Invariant (Div1 f) where     invmap _ = contramap-instance Divise (Div1 f) where-    divise f (Div1 g x xs) = Div1 (assoc . first g . f) x-                           . divise id xs-                           . toDiv -instance HFunctor Div1 where-    hmap = hoistDiv1-instance Inject Div1 where-    inject = liftDiv1 instance Divise f => Interpret Div1 f where     interpret = runDiv1 +-- | Pattern matching on a 'Div1', exposing the raw @f@ instead of+-- having it wrapped in a 'Coyoneda'.  This is the analogue of+-- 'Data.Functor.Apply.Ap1' and essentially treats the "cons" of the+-- 'Div1' as a contravariant day convolution.+--+-- Before v0.3.3.0, this used to be the concrete constructor of 'Div1'.+-- After, it is now an abstract pattern.+--+-- @since 0.3.3.0+pattern Div1_ :: (a -> (b, c)) -> f b -> Div f c -> Div1 f a+pattern Div1_ f x xs <- (div1_->CD.Day x xs f)+  where+    Div1_ f x (Div xs) = Div1 $ Coyoneda (fst . f) x :| (map . contramap) (snd . f) xs+{-# COMPLETE Div1_ #-}++div1_ :: Div1 f ~> CD.Day f (Div f)+div1_ (Div1 (Coyoneda g x :| xs)) = CD.Day x (Div xs) (\y -> (g y, y))+ -- | A 'Div1' is a "non-empty" 'Div'; this function "forgets" the non-empty -- property and turns it back into a normal 'Div'.-toDiv :: Div1 f a -> Div f a-toDiv (Div1 f x xs) = Divide f x xs+toDiv :: Div1 f ~> Div f+toDiv = Div . toList . unDiv1 --- | Map over the undering context in a 'Div1'.+-- | Map over the underlying context in a 'Div1'. hoistDiv1 :: (f ~> g) -> Div1 f ~> Div1 g-hoistDiv1 f (Div1 g x xs) = Div1 g (f x) (hoistDiv f xs)+hoistDiv1 = hmap  -- | Inject a single action in @f@ into a @'Div' f@. liftDiv1 :: f ~> Div1 f-liftDiv1 f = Div1 (,()) f Conquer+liftDiv1 = inject  -- | Interpret a 'Div1' into a context @g@, provided @g@ is 'Divise'. runDiv1 :: Divise g => (f ~> g) -> Div1 f ~> g-runDiv1 f (Div1 g x xs) = runDiv1_ f g x xs--runDiv1_-    :: forall f g a b c. Divise g-    => (f ~> g)-    -> (a -> (b, c))-    -> f b-    -> Div f c-    -> g a-runDiv1_ f = go+runDiv1 f = foldr1 (divise (\y->(y,y))) . fmap go . unDiv1   where-    go :: (x -> (y, z)) -> f y -> Div f z -> g x-    go g x = \case-      Conquer       -> contramap (fst . g) (f x)-      Divide h y ys -> divise g (f x) (go h y ys)+    go (Coyoneda g x) = contramap g (f x)  -- | 'Div1' is isomorphic to 'NonEmptyF' for contravariant @f@.  This -- witnesses one way of that isomorphism.------ Be aware that this is essentially O(n^2). div1NonEmptyF :: Contravariant f => Div1 f ~> NonEmptyF f-div1NonEmptyF (Div1 f x xs) = NonEmptyF $-       contramap (fst . f) x-    :| runListF (divListF (contramap (snd . f) xs))+div1NonEmptyF = NonEmptyF . fmap lowerCoyoneda . unDiv1  -- | 'Div1' is isomorphic to 'NonEmptyF' for contravariant @f@.  This -- witnesses one way of that isomorphism.------ This direction is O(n), unlike 'div1NonEmptyF'. nonEmptyFDiv1 :: NonEmptyF f ~> Div1 f-nonEmptyFDiv1 (NonEmptyF (x :| xs)) =-    Div1 (\y -> (y,y)) x (listFDiv (ListF xs))+nonEmptyFDiv1 = Div1 . fmap liftCoyoneda . runNonEmptyF  -- | The free 'Decide'.  Used to aggregate multiple possible consumers, -- directing the input into an appropriate consumer.@@ -219,7 +210,7 @@ instance Conclude f => Interpret Dec f where     interpret = runDec --- | Map over the undering context in a 'Dec'.+-- | Map over the underlying context in a 'Dec'. hoistDec :: forall f g. (f ~> g) -> Dec f ~> Dec g hoistDec f = go   where
src/Data/HBifunctor/Associative.hs view
@@ -87,6 +87,7 @@ import           Data.List.NonEmpty                        (NonEmpty(..)) import           Data.Void import           GHC.Generics+import qualified Data.Functor.Contravariant.Coyoneda       as CCY import qualified Data.Functor.Contravariant.Day            as CD import qualified Data.Functor.Contravariant.Night          as N import qualified Data.Functor.Day                          as D@@ -393,7 +394,7 @@ -- -- *    If @h@ is unconstrained, there are no constraints on @b@ -- *    If @h@ must be 'Divise', or 'Divisible', @b@ needs to be an instance of 'Semigroup'--- *    If @h@ must be 'Divivisible', then @b@ needs to be an instance of 'Monoid'.+-- *    If @h@ must be 'Divisible', then @b@ needs to be an instance of 'Monoid'. -- -- For some constraints (like 'Monad'), this will not be usable. --@@ -482,12 +483,14 @@     associating = isoF CD.assoc CD.disassoc      appendNE (CD.Day x y f) = divise f x y-    matchNE (Div1 f x xs) = case xs of-      Conquer -> L1 $ contramap (fst . f) x-      Divide g y ys -> R1 $ CD.Day x (Div1 g y ys) f+    matchNE = hbimap CCY.lowerCoyoneda go . matchNE @(:*:) . NonEmptyF . unDiv1+      where+        go (CCY.Coyoneda f x :*: NonEmptyF xs) = CD.Day x (Div1 xs) (\y -> (f y, y)) -    consNE (CD.Day x y f) = Div1 f x (toDiv y)-    toNonEmptyBy (CD.Day x y f) = Div1 f x (inject y)+    consNE (CD.Day x (Div1 xs) f) = Div1 . runNonEmptyF . consNE $+        CCY.Coyoneda (fst . f) x :*: contramap (snd . f) (NonEmptyF xs)+    toNonEmptyBy (CD.Day x y f) = Div1 . runNonEmptyF . toNonEmptyBy $+        CCY.Coyoneda (fst . f) x :*: CCY.Coyoneda (snd . f) y  -- | @since 0.3.0.0 instance Divise f => SemigroupIn CD.Day f where
src/Data/HBifunctor/Tensor.hs view
@@ -103,6 +103,7 @@ import           Data.Kind import           Data.List.NonEmpty                        (NonEmpty(..)) import           GHC.Generics+import qualified Data.Functor.Contravariant.Coyoneda       as CCY import qualified Data.Functor.Contravariant.Day            as CD import qualified Data.Functor.Contravariant.Night          as N import qualified Data.Functor.Day                          as D@@ -580,17 +581,16 @@     elim2 = CD.day2      appendLB (CD.Day x y z) = divide z x y-    splitNE (Div1 f x xs) = CD.Day x xs f-    splittingLB = isoF to_ from_+    splitNE = go . splitNE @(:*:) . NonEmptyF . unDiv1       where-        to_ = \case-          Conquer       -> L1 Proxy-          Divide f x xs -> R1 (CD.Day x xs f)-        from_ = \case-          L1 Proxy           -> Conquer-          R1 (CD.Day x xs f) -> Divide f x xs+        go (CCY.Coyoneda f x :*: ListF xs) = CD.Day x (Div xs) (\y -> (f y, y))+    splittingLB = isoF (ListF . unDiv) (Div . runListF) . splittingLB @(:*:) . isoF (hright to_) (hright from_)+      where+        to_   (CCY.Coyoneda f x :*: ListF xs) = CD.Day x (Div xs) (\y -> (f y, y))+        from_ (CD.Day x (Div xs) f) = CCY.Coyoneda (fst . f) x :*: contramap (snd . f) (ListF xs) -    toListBy (CD.Day x y z) = Divide z x (inject y)+    toListBy (CD.Day x y f) = Div . runListF . toListBy $+        CCY.Coyoneda (fst . f) x :*: CCY.Coyoneda (snd . f) y  -- | Instances of 'Divisible' are monoids in the monoidal category on -- contravariant 'CD.Day'.@@ -759,10 +759,9 @@ -- -- @since 0.3.0.0 instance Matchable CD.Day Proxy where-    unsplitNE (CD.Day x xs f) = Div1 f x xs-    matchLB = \case-      Conquer       -> L1 Proxy-      Divide f x xs -> R1 (Div1 f x xs)+    unsplitNE (CD.Day x (Div xs) f) = Div1 . runNonEmptyF . unsplitNE $+      CCY.Coyoneda (fst . f) x :*: contramap (snd . f) (ListF xs)+    matchLB = hright (Div1 . runNonEmptyF) . matchLB @(:*:) . ListF . unDiv  -- | @since 0.3.0.0 instance Matchable Night Not where
src/Data/HFunctor.hs view
@@ -27,6 +27,9 @@   -- * 'HFunctor' Combinators   , HLift(..), retractHLift   , HFree(..), foldHFree, retractHFree+  -- * Utility functions+  , injectMap+  , injectContramap   ) where  import           Control.Applicative.Backwards@@ -363,6 +366,20 @@     inject :: f ~> t f      {-# MINIMAL inject #-}++-- | A useful wrapper over the common pattern of+-- fmap-before-inject/inject-and-fmap.+--+-- @since 0.3.3.0+injectMap :: (Inject t, Functor f) => (a -> b) -> f a -> t f b+injectMap f = inject . fmap f++-- | A useful wrapper over the common pattern of+-- contramap-before-inject/inject-and-contramap.+--+-- @since 0.3.3.0+injectContramap :: (Inject t, Contravariant f) => (a -> b) -> f b -> t f a+injectContramap f = inject . contramap f  -- | 'HBind' is effectively a "higher-order 'Monad'", in the sense that -- 'HFunctor' is a "higher-order 'Functor'".