-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Isos & Lens for Data.Diverse.Many and Prisms for Data.Diverse.Which
--   
--   Isos &amp; Lens for Data.Diverse.Many and Prisms for
--   Data.Diverse.Which Refer to <a>ManySpec.hs</a> and <a>WhichSpec.hs</a>
--   for example usages.
@package data-diverse-lens
@version 4.3.0.0

module Data.Diverse.Lens.Many

-- | <pre>
--   _Many = iso fromMany toMany
--   </pre>
_Many :: IsMany t xs a => Iso' (Many xs) (t xs a)

-- | <pre>
--   _Many' = iso fromMany' toMany'
--   </pre>
_Many' :: IsMany Tagged xs a => Iso' (Many xs) a

-- | A type class for extensible product.
--   
--   We provide instances for tuples up to 12 elements by default. You can
--   define your own instance of <a>Has</a>, but most of the time tuples
--   will do fine.
class Has a t
getter :: Has a t => t -> a
modifier :: Has a t => a -> a -> t -> t
hasLens :: Has a t => Lens t a
hasTag :: forall l a s. Has (Tagged l a) s => Lens' s a
hadTag :: forall l a b s. Had (Tagged l a) s => Lens s (Replaced (Tagged l a) (Tagged l b) s) a b

-- | Polymorphic version of <tt>has'</tt>
class (Has a s, Replaced a a s ~ s) => Had a s where {
    type family Replaced a b s;
}
hadLens :: Had a s => Lens s (Replaced a b s) a b

-- | <a>grabL</a> (<a>view</a> <a>hasL</a>) and <a>replaceL</a> (<a>set</a>
--   <a>hasL</a>) in <a>Lens'</a> form.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> <a>nil</a>
--   x <a>^.</a> <tt>hasL'</tt> @Foo `shouldBe` Tagged @Foo False
--   (x <a>&amp;</a> <tt>hasL'</tt> @Foo <a>.~</a> Tagged @Foo True) `shouldBe` (5 :: Int) <a>./</a> Tagged @Foo True <a>./</a> Tagged @Bar 'X' <a>./</a> <a>nil</a>
--   </pre>
--   
--   A default implementation using generics is not provided as it make GHC
--   think that <tt>l</tt> must be type <tt>Symbol</tt> when <tt>l</tt> can
--   actually be any kind. Create instances of <a>HasL</a> using
--   <a>Data.Generics.Product.Fields</a> as follows: <tt> instance
--   HasField' l Foo a =&gt; hasL' l a Foo where hasL' = field </tt>l
--   default hasL' :: forall (l :: Symbol) a s. (HasField' l s a) =&gt;
--   Lens' s a hasL' = field @l
class HasL (l :: k) a s | s l -> a
hasL :: HasL l a s => Lens' s a

-- | Polymorphic version of <tt>hasL'</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> <a>nil</a>
--   (x <a>&amp;</a> <a>hasL</a> @Foo <a>.~</a> "foo") `shouldBe` (5 :: Int) <a>./</a> "foo" <a>./</a> Tagged @Bar 'X' <a>./</a> <a>nil</a>
--   </pre>
class (HasL (l :: k) a s, ReplacedL l a a s ~ s) => HadL (l :: k) a s | s l -> a where {
    type family ReplacedL l a b s;
}
hadL :: HadL l a s => Lens s (ReplacedL l a b s) a b

-- | <a>grabN</a> (<a>view</a> <a>has</a>) and <a>replaceN'</a> (<a>set</a>
--   <tt>has'</tt>) in <a>Lens'</a> form.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' ./ nil
--   x <a>^.</a> <tt>hasN'</tt> @0 `shouldBe` 5
--   (x <a>&amp;</a> <tt>hasN'</tt> @0 <a>.~</a> 6) `shouldBe` (6 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   </pre>
class HasN (n :: Nat) a s | s n -> a
hasN :: HasN n a s => Lens' s a

-- | Polymorphic version of <tt>hasN'</tt>
class (HasN (n :: Nat) a s, ReplacedN n a a s ~ s) => HadN (n :: Nat) a s | s n -> a where {
    type family ReplacedN n a b s;
}
hadN :: HadN n a s => Lens s (ReplacedN n a b s) a b

-- | A friendlier constraint synonym for <a>project</a>.
type Project (smaller :: [Type]) (smaller' :: [Type]) (larger :: [Type]) (larger' :: [Type]) = (Select smaller larger, Amend smaller smaller' larger, larger' ~ Replaces smaller smaller' larger)

-- | Polymorphic version of project'
project :: forall smaller smaller' larger larger'. Project smaller smaller' larger larger' => Lens (Many larger) (Many larger') (Many smaller) (Many smaller')

-- | A friendlier constraint synonym for <a>project'</a>.
type Project' (smaller :: [Type]) (larger :: [Type]) = (Select smaller larger, Amend' smaller larger)

-- | <a>select</a> (<a>view</a> <a>project</a>) and <a>amend</a>
--   (<a>set</a> <a>project</a>) in <a>Lens'</a> form.
--   
--   <pre>
--   <a>project</a> = <a>lens</a> <a>select</a> <a>amend</a>
--   </pre>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   x <a>^.</a> (<a>project'</a> @_ @'[Int, Maybe Char]) `shouldBe` (5 :: Int) <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   (x <a>&amp;</a> (<a>project'</a> @_ @'[Int, Maybe Char]) <a>.~</a> ((6 :: Int) <a>./</a> Just <tt>P</tt> <a>./</a> <a>nil</a>)) `shouldBe`
--       (6 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'P' <a>./</a> <a>nil</a>
--   </pre>
project' :: forall smaller larger. Project' smaller larger => Lens' (Many larger) (Many smaller)

-- | A friendlier constraint synonym for <a>projectL</a>.
type ProjectL (ls :: [k]) (smaller :: [Type]) (smaller' :: [Type]) (larger :: [Type]) (larger' :: [Type]) = (Select smaller larger, Amend smaller smaller' larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger, larger' ~ Replaces smaller smaller' larger)

-- | Polymorphic version of <a>projectL'</a>
--   
--   <pre>
--   let x = False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   (x <a>&amp;</a> (<a>projectL</a> @'["Hi", "Bye"] <a>.~</a> (True <a>./</a> Tagged @"Changed" False <a>./</a> <a>nil</a>)) `shouldBe`
--       False <a>./</a> True <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Changed" False <a>./</a> <a>nil</a>
--   </pre>
projectL :: forall ls smaller smaller' larger larger'. ProjectL ls smaller smaller' larger larger' => Lens (Many larger) (Many larger') (Many smaller) (Many smaller')

-- | A friendlier constraint synonym for <a>projectL'</a>.
type ProjectL' (ls :: [k]) (smaller :: [Type]) (larger :: [Type]) = (Select smaller larger, Amend' smaller larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger)

-- | <a>selectL</a> (<a>view</a> <a>projectL</a>) and <a>amendL</a>
--   (<a>set</a> <a>projectL</a>) in <a>Lens'</a> form.
--   
--   <pre>
--   let x = False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   x <a>^.</a> (<a>projectL'</a> @'[Foo, Bar] `shouldBe` Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> nil
--   (x <a>&amp;</a> (<a>projectL'</a> @'["Hi", "Bye"] <a>.~</a> (Tagged @"Hi" (6 :: Int) <a>./</a> Tagged @"Bye" 'P' <a>./</a> nil)) '<tt>shouldBe</tt>
--       False <a>./</a> Tagged @"Hi" (6 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Bye" 'P' <a>./</a> <a>nil</a>
--   </pre>
projectL' :: forall ls smaller larger. ProjectL' ls smaller larger => Lens' (Many larger) (Many smaller)

-- | A friendlier constraint synonym for <a>projectN</a>.
type ProjectN (ns :: [Nat]) (smaller :: [Type]) (smaller' :: [Type]) (larger :: [Type]) (larger' :: [Type]) = (SelectN ns smaller larger, AmendN ns smaller smaller' larger, larger' ~ ReplacesIndex ns smaller' larger)

-- | Polymorphic version of <a>projectN'</a>
projectN :: forall ns smaller smaller' larger larger'. ProjectN ns smaller smaller' larger larger' => Lens (Many larger) (Many larger') (Many smaller) (Many smaller')

-- | A friendlier constraint synonym for <a>projectN'</a>.
type ProjectN' (ns :: [Nat]) (smaller :: [Type]) (larger :: [Type]) = (SelectN ns smaller larger, AmendN' ns smaller larger)

-- | <a>selectN</a> (<a>view</a> <a>projectN</a>) and <a>amendN</a>
--   (<a>set</a> <a>projectN</a>) in <a>Lens'</a> form.
--   
--   <pre>
--   <a>projectN</a> = <a>lens</a> <a>selectN</a> <a>amendN</a>
--   </pre>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   x <a>^.</a> <a>projectN</a> @_ @'[5, 4, 0] `shouldBe` Just 'A' <a>./</a> (6 :: Int) <a>./</a> (5 ::Int) <a>./</a> <a>nil</a>
--   (x <a>&amp;</a> <a>projectN</a> @_ @'[5, 4, 0] <a>.~</a> (Just 'B' <a>./</a> (8 :: Int) <a>./</a> (4 ::Int) <a>./</a> nil)) `shouldBe`
--       (4 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (8 :: Int) <a>./</a> Just 'B' <a>./</a> <a>nil</a>
--   </pre>
projectN' :: forall ns smaller larger. ProjectN' ns smaller larger => Lens' (Many larger) (Many smaller)
instance Data.Diverse.TypeLevel.MemberAt n x xs => Data.Diverse.Lens.Many.HadN n x (Data.Diverse.Many.Internal.Many xs)
instance Data.Diverse.TypeLevel.MemberAt n x xs => Data.Diverse.Lens.Many.HasN n x (Data.Diverse.Many.Internal.Many xs)
instance forall k (l :: k) (xs :: [*]) x. (Data.Diverse.TypeLevel.UniqueLabelMember l xs, x ~ Data.Diverse.TypeLevel.KindAtLabel l xs) => Data.Diverse.Lens.Many.HadL l x (Data.Diverse.Many.Internal.Many xs)
instance forall k (l :: k) (xs :: [*]) x. (Data.Diverse.TypeLevel.UniqueLabelMember l xs, x ~ Data.Diverse.TypeLevel.KindAtLabel l xs) => Data.Diverse.Lens.Many.HasL l x (Data.Diverse.Many.Internal.Many xs)
instance Data.Diverse.TypeLevel.UniqueMember x xs => Data.Diverse.Lens.Many.Had x (Data.Diverse.Many.Internal.Many xs)
instance Data.Diverse.TypeLevel.UniqueMember x xs => Data.Has.Has x (Data.Diverse.Many.Internal.Many xs)

module Data.Diverse.Lens.Which

-- | <a>pick</a> (<a>review</a> <a>facet</a>) and <a>trial</a>
--   (<a>preview</a> <a>facet</a>) in <a>Prism'</a> form.
--   
--   <pre>
--   <a>facet</a> = <a>prism'</a> <a>pick</a> (<a>trial'</a>)
--   </pre>
--   
--   <pre>
--   let y = <a>review</a> (<a>facet</a> @Int) (5 :: Int) :: <a>Which</a> '[Bool, Int, Char, Bool, Char] -- <a>pick</a>
--       x = <a>preview</a> (<a>facet</a> @Int) y -- <a>trial</a>
--   x `shouldBe` (Just 5)
--   </pre>
class AsFacet a s
facet :: AsFacet a s => Prism' s a
class AsFacet a s => MatchingFacet a s t | s a -> t

-- | Unfortunately, polymorphic <tt>Prism s t a b</tt> cannot be used as it
--   can only be created with: <tt> (UniqueMember x xs, UniqueMember y ys,
--   ys ~ Remove x xs) =&gt; prism (pick :: y -&gt; Which ys) (trial ::
--   Which xs -&gt; Either (Which ys) x) </tt> This above causes problems
--   when used monomorphically with <tt>s ~ t</tt> and <tt>x ~ y</tt> since
--   <tt>xs</tt> cannot equal <tt>ys ~ Remove x x</tt>.
--   
--   What is desired is: (UniqueMember x xs, ys ~ Remove x xs) =&gt; prism_
--   (pick :: x -&gt; Which xs) (trial :: Which xs -&gt; Either (Which ys)
--   x)
--   
--   So we expose the polymorphic <a>matching</a> explicitly.
matchingFacet :: MatchingFacet a s t => s -> Either t a

-- | Variation of <a>facet</a> specialized to <a>Tagged</a> which
--   automatically tags and untags the field. A default implementation
--   using generics is not provided as it make GHC think that <tt>l</tt>
--   must be type <tt>Symbol</tt> when <tt>l</tt> can actually be any kind.
facetTag :: forall l a s. (AsFacet (Tagged l a) s) => Prism' s a

-- | Untagged version of <a>MatchingFacet</a>
matchingFacetTag :: forall l a s t. MatchingFacet (Tagged l a) s t => s -> Either t a

-- | <a>pickL</a> (<a>review</a> <a>facetL</a>) and <a>trialL'</a>
--   (<a>preview</a> <tt>facetL'</tt>) in <a>Prism'</a> form.
--   
--   <pre>
--   let y = <a>review</a> <a>facetL</a> @Bar (Tagged (5 :: Int)) :: Which '[Tagged Foo Bool, Tagged Bar Int, Char, Bool, Char]
--       x = <a>preview</a> <a>facetL</a> @Bar y
--   x `shouldBe` (Just (Tagged 5))
--   </pre>
class AsFacetL (l :: k) a s | s l -> a
facetL :: AsFacetL l a s => Prism' s a

-- | Labelled version of <a>MatchingFacet</a>
class AsFacetL l a s => MatchingFacetL l a s t | s a -> t
matchingFacetL :: MatchingFacetL l a s t => s -> Either t a

-- | <a>pickN</a> (<a>review</a> <a>facetN</a>) and <a>trialN</a>
--   (<a>preview</a> <a>facetN</a>) in <a>Prism'</a> form.
--   
--   <pre>
--   <a>facetN</a> p = <a>prism'</a> (<a>pickN</a> p) (<a>trialN'</a> p)
--   </pre>
--   
--   <pre>
--   let y = <a>review</a> (<a>facetN</a> @4) (5 :: Int) :: <a>Which</a> '[Bool, Int, Char, Bool, Int, Char] -- <a>pickN</a>
--       x = <a>preview</a> (<a>facetN</a> @4) y -- <a>trialN</a>
--   x `shouldBe` (Just 5)
--   </pre>
class AsFacetN (n :: Nat) a s | s n -> a
facetN :: AsFacetN n a s => Prism' s a

-- | Nat indexed version of <a>MatchingFacet</a>
class AsFacetN n a s => MatchingFacetN n a s t | s a -> t
matchingFacetN :: MatchingFacetN n a s t => s -> Either t a

-- | A friendlier constraint synonym for <a>inject</a>
type Inject (branch :: [Type]) (tree :: [Type]) = (Diversify branch tree, Reinterpret' branch tree)

-- | <a>diversify</a> (<a>review</a> <a>inject</a>) and <a>reinterpret'</a>
--   (<a>preview</a> <a>inject</a>) in <a>Prism'</a> form.
--   
--   <pre>
--   let x = <a>pick</a> (5 :: Int) :: <a>Which</a> '[String, Int]
--       y = <a>review</a> (<a>inject</a> @_  @_ @[Bool, Int, Char, String]) x -- <a>diversify</a>
--   y `shouldBe` pick (5 :: Int) :: <a>Which</a> '[Bool, Int, Char, String]
--   let y' = <a>preview</a> (<a>inject</a> @_ @[String, Int]) y -- <a>reinterpret</a>
--   y' `shouldBe` Just (pick (5 :: Int)) :: Maybe (<a>Which</a> '[String, Int])
--   </pre>
inject :: forall branch tree. (Inject branch tree) => Prism' (Which tree) (Which branch)

-- | A friendlier constraint synonym for <a>injectL</a>
type InjectL (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Diversify branch tree, Reinterpret' branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | <a>diversifyL</a> (<a>review</a> <a>injectL</a>) and
--   <a>reinterpretL'</a> (<a>preview</a> <a>injectL</a>) in <a>Prism'</a>
--   form.
--   
--   <pre>
--   let t = <a>pick</a> @[Tagged Bar Int, Tagged Foo Bool, Tagged Hi Char, Tagged Bye Bool] (5 :: Tagged Bar Int)
--       b = <a>pick</a> @'[Tagged Foo Bool, Tagged Bar Int] (5 :: Tagged Bar Int)
--       t' = <a>review</a> (<a>injectL</a> @_ @[Foo, Bar] @_ @[Tagged Bar Int, Tagged Foo Bool, Tagged Hi Char, Tagged Bye Bool]) b
--       b' = <a>preview</a> (<a>injectL</a> @_ @[Foo, Bar]) t'
--   t `shouldBe` t'
--   b' `shouldBe` Just b
--   </pre>
injectL :: forall ls branch tree. InjectL ls branch tree => Prism' (Which tree) (Which branch)

-- | A friendlier constraint synonym for <a>injectN</a>
type InjectN (ns :: [Nat]) (branch :: [Type]) (tree :: [Type]) = (DiversifyN ns branch tree, ReinterpretN' ns branch tree)

-- | <a>diversifyN</a> (<a>review</a> <a>injectN</a>) and
--   <a>reinterpretN'</a> (<a>preview</a> <a>injectN</a>) in <a>Prism'</a>
--   form.
--   
--   <pre>
--   let x = <a>pick</a> (5 :: Int) :: <a>Which</a> '[String, Int]
--       y = <a>review</a> (injectN @_ @[3, 1] @_ @[Bool, Int, Char, String]) x -- <a>diversifyN</a>
--   y `shouldBe` pick (5 :: Int) :: <a>Which</a> '[Bool, Int, Char, String]
--   let y' = <a>preview</a> (<a>injectN</a> @_ @[3, 1] @[String, Int]) y -- <tt>reinterpertN'</tt>
--   y' `shouldBe` Just (<a>pick</a> (5 :: Int)) :: Maybe (<a>Which</a> '[String, Int])
--   </pre>
injectN :: forall ns branch tree. InjectN ns branch tree => Prism' (Which tree) (Which branch)
instance (Data.Diverse.TypeLevel.MemberAt n x xs, ys ~ Data.Diverse.TypeLevel.RemoveIndex n xs) => Data.Diverse.Lens.Which.MatchingFacetN n x (Data.Diverse.Which.Internal.Which xs) (Data.Diverse.Which.Internal.Which ys)
instance Data.Diverse.TypeLevel.MemberAt n x xs => Data.Diverse.Lens.Which.AsFacetN n x (Data.Diverse.Which.Internal.Which xs)
instance forall k (l :: k) (xs :: [*]) x (ys :: [*]). (Data.Diverse.TypeLevel.UniqueLabelMember l xs, x ~ Data.Diverse.TypeLevel.KindAtLabel l xs, ys ~ Data.Diverse.TypeLevel.Remove x xs) => Data.Diverse.Lens.Which.MatchingFacetL l x (Data.Diverse.Which.Internal.Which xs) (Data.Diverse.Which.Internal.Which ys)
instance forall k (l :: k) (xs :: [*]) x. (Data.Diverse.TypeLevel.UniqueLabelMember l xs, x ~ Data.Diverse.TypeLevel.KindAtLabel l xs) => Data.Diverse.Lens.Which.AsFacetL l x (Data.Diverse.Which.Internal.Which xs)
instance (Data.Diverse.TypeLevel.UniqueMember x xs, ys ~ Data.Diverse.TypeLevel.Remove x xs) => Data.Diverse.Lens.Which.MatchingFacet x (Data.Diverse.Which.Internal.Which xs) (Data.Diverse.Which.Internal.Which ys)
instance Data.Diverse.Lens.Which.AsFacet Data.Void.Void (Data.Diverse.Which.Internal.Which '[])
instance Data.Diverse.Lens.Which.AsFacet (Data.Diverse.Which.Internal.Which '[]) Data.Void.Void
instance Data.Diverse.Lens.Which.AsFacet x x
instance Data.Diverse.TypeLevel.UniqueMember x xs => Data.Diverse.Lens.Which.AsFacet x (Data.Diverse.Which.Internal.Which xs)

module Data.Diverse.Lens

module Data.Diverse.Profunctor.Many

-- | A friendlier constraint synonym for <a>have</a>.
type Have a b s t = (Had a s, t ~ Replaced a b s)

-- | Like <a>Strong</a> or <a>Arrow</a> but lifting into <a>Many</a>
have :: forall w a b s t. (Profunctor w, Strong w, Have a b s t) => w a b -> w s t

-- | <a>have</a> under <a>Kleisli</a>
haveK :: forall m a b s t. (Monad m, Have a b s t) => (a -> m b) -> (s -> m t)

-- | A friendlier constraint synonym for <a>projected</a>.
type Projected a1 a2 b1 b2 = (Select a1 a2, Amend a1 b1 a2, b2 ~ Replaces a1 b1 a2)

-- | Like <a>Strong</a> or <a>Arrow</a> but lifting from a <a>Many</a> to a
--   <a>Many</a> of another type
projected :: forall w a1 a2 b1 b2. (Strong w, Projected a1 a2 b1 b2) => w (Many a1) (Many b1) -> w (Many a2) (Many b2)

-- | <a>projected</a> under <a>Kleisli</a>
projectedK :: forall m a1 a2 b1 b2. (Monad m, Projected a1 a2 b1 b2) => (Many a1 -> m (Many b1)) -> (Many a2 -> m (Many b2))
type MakeFrom a1 a2 a3 = (Select a1 a3, Select a2 a3, a3 ~ AppendUnique a1 a2)

-- | A friendlier constraint synonym for <tt>*&amp;&amp;*</tt>.
type MakeBoth b1 b2 b3 = (b3 ~ Append b1 b2)

-- | Split the input between the two argument arrows and combine their
--   output. The type of the resultant input is a <a>Many</a> of all the
--   unique types in the argument arrows' inputs, The type of the resultant
--   output is a concatenated <a>Many</a> of the arguments arrows' outputs.
--   Analogous to a <a>Many</a> combination of both of <a>***</a> and
--   <a>&amp;&amp;&amp;</a>. It is a compile error if the types are not
--   distinct in each of the argument arrow inputs.
makeBesides :: forall w a1 a2 a3 b1 b2 b3. (Category w, Strong w, MakeFrom a1 a2 a3, MakeBoth b1 b2 b3) => w (Many a1) (Many b1) -> w (Many a2) (Many b2) -> w (Many a3) (Many b3)
infixr 3 `makeBesides`
makeBesidesK :: forall m a1 a2 a3 b1 b2 b3. (Monad m, MakeFrom a1 a2 a3, MakeBoth b1 b2 b3) => (Many a1 -> m (Many b1)) -> (Many a2 -> m (Many b2)) -> (Many a3 -> m (Many b3))
infixr 3 `makeBesidesK`

-- | Left-to-right chaining of arrows one after another, where left over
--   input not consumed by the right arrow is forwarded to the output. It
--   is a compile error if the types are not distinct in each of the
--   argument arrow inputs, or if the input of the second arrow is not a
--   complete subset of the output of the first arrow.
thenMake :: forall w a a2 b1 b2 b3. (Category w, Strong w, Projected a2 b1 b2 b3) => w a (Many b1) -> w (Many a2) (Many b2) -> w a (Many b3)
infixr 3 `thenMake`
thenMakeK :: forall m a a2 b1 b2 b3. (Monad m, Projected a2 b1 b2 b3) => (a -> m (Many b1)) -> (Many a2 -> m (Many b2)) -> (a -> m (Many b3))
infixr 3 `thenMakeK`

module Data.Diverse.Profunctor.Which

-- | A friendlier constraint synonym for <a>faceted</a>.
type Faceted a as x b bs y = (MatchingFacet a x y, AsFacet b y)

-- | Like <a>Choice</a> or <a>ArrowChoice</a> but lifting into a
--   polymorphic variant.
faceted :: forall w a as x b bs y. (Choice w, Faceted a as x b bs y) => w a b -> w x y

-- | <a>faceted</a> under <a>Kleisli</a>
facetedK :: forall m a as x b bs y. (Monad m, Faceted a as x b bs y) => (a -> m b) -> (x -> m y)

-- | A friendlier constraint synonym for <a>injected</a>.
type Injected a2 a3 b2 b3 = (Reinterpret a2 a3, ChooseBoth (Complement a3 a2) b2 b3, Complement a2 a3 ~ '[])

-- | Like <a>Choice</a> or <a>ArrowChoice</a> but lifting from <a>Which</a>
--   into another type of <a>Which</a> NB. It is a compile error if all of
--   the input types in the second arrow <tt>a</tt> is not the output types
--   of the first arrow. This prevents surprising behaviour where the
--   second arrow is completely ignored.
injected :: forall w a2 a3 b2 b3. (Choice w, Injected a2 a3 b2 b3) => w (Which a2) (Which b2) -> w (Which a3) (Which b3)

-- | <a>injected</a> under <a>Kleisli</a>
injectedK :: forall m a2 a3 b2 b3. (Monad m, Injected a2 a3 b2 b3) => (Which a2 -> m (Which b2)) -> (Which a3 -> m (Which b3))

-- | A friendlier constraint synonym for <tt>chooseFrom</tt>. Redundant
--   constraint: <tt>a3 ~ Append a1 a2</tt> is redundant but narrows down
--   <tt>a3</tt>
type ChooseFrom a1 a2 a3 = (Reinterpret a2 a3, a1 ~ Complement a3 a2, a3 ~ Append a1 a2)

-- | A friendlier constraint synonym for <tt>chooseBoth</tt>. Redundant
--   constraint: <tt>b3 ~ AppendUnique b1 b2</tt> is redundant but narrows
--   down <tt>b3</tt>
type ChooseBoth b1 b2 b3 = (Diversify b1 b3, Diversify b2 b3, b3 ~ AppendUnique b1 b2)

-- | Split the input between the two argument arrows, retagging and merging
--   their outputs. The output is merged into a <a>Which</a> of unique
--   types. Analogous to a <a>Which</a> combination of both <a>+++</a> and
--   <a>|||</a>. It is a compile error if the types are not distinct after
--   <a>Append</a>ing both argument arrows inputs. This is to prevent
--   accidently processing an input type twice. The compile error will be
--   due to <tt>(Append a1 a2)</tt> which will not satisfy
--   <tt>UniqueMember</tt> constraints in <a>Reinterpret</a>.
chooseBetween :: forall w a1 a2 a3 b1 b2 b3. (Category w, Choice w, ChooseFrom a1 a2 a3, ChooseBoth b1 b2 b3) => w (Which a1) (Which b1) -> w (Which a2) (Which b2) -> w (Which a3) (Which b3)
infixr 2 `chooseBetween`

-- | <a>chooseBetween</a> under <a>Kleisli</a>
chooseBetweenK :: forall m a1 a2 a3 b1 b2 b3. (Monad m, ChooseFrom a1 a2 a3, ChooseBoth b1 b2 b3) => (Which a1 -> m (Which b1)) -> (Which a2 -> m (Which b2)) -> (Which a3 -> m (Which b3))
infixr 2 `chooseBetweenK`

-- | Left-to-right chaining of arrows one after another, where left over
--   possibilities not handled by the right arrow is forwarded to the
--   output. It is a compile error if the types are not distinct in each of
--   the argument arrow inputs, or if the types are not distinct in each of
--   the argument arrow output. NB. It is currently not a compile error if
--   the input of the second arrow is distinct from the output of the first
--   arrrow, in which case this function does not change anything except to
--   add the types of the second arrow to the output.
thenChoose :: forall w a a2 b1 b2 b3. (Category w, Choice w, Injected a2 b1 b2 b3) => w a (Which b1) -> w (Which a2) (Which b2) -> w a (Which b3)
infixr 2 `thenChoose`

-- | <a>thenChoose</a> under <a>Kleisli</a>
thenChooseK :: forall m a a2 b1 b2 b3. (Monad m, Injected a2 b1 b2 b3) => (a -> m (Which b1)) -> (Which a2 -> m (Which b2)) -> (a -> m (Which b3))
infixr 2 `thenChooseK`
chooseWith :: (Functor f, ChooseBoth a1 a2 a3) => (f (Which a3) -> f (Which a3) -> f (Which a3)) -> f (Which a1) -> f (Which a2) -> f (Which a3)
infixr 6 `chooseWith`

module Data.Diverse.Profunctor
