| Copyright | (c) Justin Le 2019 | 
|---|---|
| License | BSD3 | 
| Maintainer | justin@jle.im | 
| Stability | experimental | 
| Portability | non-portable | 
| Safe Haskell | Safe-Inferred | 
| Language | Haskell2010 | 
Data.HBifunctor.Tensor
Description
This module provides tools for working with binary functor combinators.
Data.Functor.HFunctor deals with single functor combinators (transforming a single functor). This module provides tools for working with combinators that combine and mix two functors "together".
The binary analog of HFunctor is HBifunctor: we can map
 a structure-transforming function over both of the transformed functors.
Tensor gives some extra properties of your binary functor combinator:
 associativity and identity (see docs for Tensor for more details).
The binary analog of Interpret is MonoidIn.  If your combinator t
 and target functor f is an instance of MonoidIn t ff.
biretract:: (f:+:f) a -> f apureT::V1a -> f a biretract ::Plusf => (f:*:f) a -> f a pureT :: Plus f =>Proxya -> f a biretract ::Applicativef =>Dayf f a -> f a pureT :: Applicative f =>Identitya -> f a biretract ::Monadf =>Compf f a -> f a pureT :: Monad f =>Identitya -> f a
Synopsis
- class (Associative t, Inject (ListBy t)) => Tensor t i | t -> i where- type ListBy t :: (Type -> Type) -> Type -> Type
- intro1 :: f ~> t f i
- intro2 :: g ~> t i g
- elim1 :: FunctorBy t f => t f i ~> f
- elim2 :: FunctorBy t g => t i g ~> g
- appendLB :: t (ListBy t f) (ListBy t f) ~> ListBy t f
- splitNE :: NonEmptyBy t f ~> t f (ListBy t f)
- splittingLB :: ListBy t f <~> (i :+: t f (ListBy t f))
- toListBy :: t f f ~> ListBy t f
- fromNE :: NonEmptyBy t f ~> ListBy t f
 
- rightIdentity :: (Tensor t i, FunctorBy t f) => f <~> t f i
- leftIdentity :: (Tensor t i, FunctorBy t g) => g <~> t i g
- sumLeftIdentity :: f <~> (V1 :+: f)
- sumRightIdentity :: f <~> (f :+: V1)
- prodLeftIdentity :: f <~> (Proxy :*: f)
- prodRightIdentity :: g <~> (g :*: Proxy)
- class (Tensor t i, SemigroupIn t f) => MonoidIn t i f where
- nilLB :: forall t i f. Tensor t i => i ~> ListBy t f
- consLB :: Tensor t i => t f (ListBy t f) ~> ListBy t f
- unconsLB :: Tensor t i => ListBy t f ~> (i :+: t f (ListBy t f))
- retractLB :: forall t i f. MonoidIn t i f => ListBy t f ~> f
- interpretLB :: forall t i g f. MonoidIn t i f => (g ~> f) -> ListBy t g ~> f
- inL :: forall t i f g. MonoidIn t i g => f ~> t f g
- inR :: forall t i f g. MonoidIn t i f => g ~> t f g
- outL :: (Tensor t Proxy, FunctorBy t f) => t f g ~> f
- outR :: (Tensor t Proxy, FunctorBy t g) => t f g ~> g
- prodOutL :: (f :*: g) ~> f
- prodOutR :: (f :*: g) ~> g
- newtype WrapF f a = WrapF {- unwrapF :: f a
 
- newtype WrapLB t f a = WrapLB {}
- class Tensor t i => Matchable t i where
- splittingNE :: (Matchable t i, FunctorBy t f) => NonEmptyBy t f <~> t f (ListBy t f)
- matchingLB :: forall t i f. (Matchable t i, FunctorBy t f) => ListBy t f <~> (i :+: NonEmptyBy t f)
Tensor
class (Associative t, Inject (ListBy t)) => Tensor t i | t -> i where Source #
An Associative HBifunctor can be a Tensor if there is some
 identity i where t i f and t f i are equivalent to just f.
That is, "enhancing" f with t i does nothing.
The methods in this class provide us useful ways of navigating
 a Tensor t
The Tensor is essentially the HBifunctor equivalent of Inject,
 with intro1 and intro2 taking the place of inject.
Formally, we can say that t enriches a the category of
 endofunctors with monoid strcture: it turns our endofunctor category
 into a "monoidal category".
Different instances of t each enrich the endofunctor category in
 different ways, giving a different monoidal category.
Associated Types
type ListBy t :: (Type -> Type) -> Type -> Type Source #
The "monoidal functor combinator" induced by t.
A value of type ListBy t f a is equivalent to one of:
- I a-- zero fs
- f a-- one f
- t f f a-- two fs
- t f (t f f) a-- three fs
- t f (t f (t f f)) a 
- t f (t f (t f (t f f))) a 
- .. etc
For example, for :*:, we have ListF.  This is because:
Proxy~ListF[] ~nilLB@(:*:) x ~ ListF [x] ~injectx x :*: y ~ ListF [x,y] ~toListBy(x :*: y) x :*: y :*: z ~ ListF [x,y,z] -- etc.
You can create an "empty" one with nilLB, a "singleton" one with
 inject, or else one from a single t f f with toListBy.
See NonEmptyBy for a "non-empty"
 version of this type.
Methods
Because t f (I t) is equivalent to f, we can always "insert"
 f into t f (I t).
This is analogous to inject from Inject, but for HBifunctors.
Because t (I t) g is equivalent to f, we can always "insert"
 g into t (I t) g.
This is analogous to inject from Inject, but for HBifunctors.
elim1 :: FunctorBy t f => t f i ~> f Source #
Witnesses the property that i is the identity of t: t
 f i always leaves f unchanged, so we can always just drop the
 i.
elim2 :: FunctorBy t g => t i g ~> g Source #
Witnesses the property that i is the identity of t: t i g
 always leaves g unchanged, so we can always just drop the i t.
appendLB :: t (ListBy t f) (ListBy t f) ~> ListBy t f Source #
If a ListBy t ft f to
 itself, then we can also "append" two ListBy t fListBy t ft fs.
Note that this essentially gives an instance for SemigroupIn
 t (ListBy t f)f; this is witnessed by
 WrapLB.
splitNE :: NonEmptyBy t f ~> t f (ListBy t f) Source #
Lets you convert an NonEmptyBy t ff to
 ListBy t f
Analogous to a function NonEmpty a -> (a,
 [a])
Note that this is not reversible in general unless we have
 Matchable t
splittingLB :: ListBy t f <~> (i :+: t f (ListBy t f)) Source #
An ListBy t ft to f
 and ListBy t f (the "head" and "tail").  This witnesses that
 isomorphism.
toListBy :: t f f ~> ListBy t f Source #
Embed a direct application of f to itself into a ListBy t f
fromNE :: NonEmptyBy t f ~> ListBy t f Source #
NonEmptyBy t ffs", and 'ListBy t f is "zero or more
 fs".  This function lets us convert from one to the other.
This is analogous to a function NonEmpty a ->
 [a]
Note that because t is not inferrable from the input or output
 type, you should call this using -XTypeApplications:
fromNE@(:*:) ::NonEmptyFf a ->ListFf a fromNE @Comp::Free1f a ->Freef a
Instances
rightIdentity :: (Tensor t i, FunctorBy t f) => f <~> t f i Source #
f is isomorphic to t f i: that is, i is the identity of t, and
 leaves f unchanged.
leftIdentity :: (Tensor t i, FunctorBy t g) => g <~> t i g Source #
g is isomorphic to t i g: that is, i is the identity of t, and
 leaves g unchanged.
sumLeftIdentity :: f <~> (V1 :+: f) Source #
leftIdentity (intro1 and elim1) for :+: actually does not
 require Functor.  This is the more general version.
sumRightIdentity :: f <~> (f :+: V1) Source #
rightIdentity (intro2 and elim2) for :+: actually does not
 require Functor.  This is the more general version.
prodLeftIdentity :: f <~> (Proxy :*: f) Source #
leftIdentity (intro1 and elim1) for :*: actually does not
 require Functor.  This is the more general version.
prodRightIdentity :: g <~> (g :*: Proxy) Source #
rightIdentity (intro2 and elim2) for :*: actually does not
 require Functor.  This is the more general version.
MonoidIn
class (Tensor t i, SemigroupIn t f) => MonoidIn t i f where Source #
This class effectively gives us a way to generate a value of f a
 based on an i a, for Tensor t ibiretract from
 SemigroupIn that weren't possible without it: it gives us a "base
 case" for recursion in a lot of cases.
Essentially, we get an i ~> f, pureT, where we can introduce an f
 a as long as we have an i a.
Formally, if we have Tensor t it give different monoidal categories.
A functor f is known as a "monoid in the (monoidal) category
 of endofunctors on t" if we can biretract:
t f f ~> f
and also pureT:
i ~> f
This gives us a few interesting results in category theory, which you can stil reading about if you don't care:
- All functors are monoids in the monoidal category
    on :+:
- The class of functors that are monoids in the monoidal
    category on :*:is exactly the functors that are instances ofPlus.
- The class of functors that are monoids in the monoidal
    category on Dayis exactly the functors that are instances ofApplicative.
- The class of functors that are monoids in the monoidal
    category on Compis exactly the functors that are instances ofMonad.
This is the meaning behind the common adage, "monads are just monoids
    in the category of endofunctors".  It means that if you enrich the
    category of endofunctors to be monoidal with Comp, then the class
    of functors that are monoids in that monoidal category are exactly
    what monads are.  However, the adage is a little misleading: there
    are many other ways to enrich the category of endofunctors to be
    monoidal, and Comp is just one of them.  Similarly, the class of
    functors that are monoids in the category of endofunctors enriched by
    Day are Applicative.
Note that instances of this class are intended to be written with t
 and i to be fixed type constructors, and f to be allowed to vary
 freely:
instance Monad f => MonoidIn Comp Identity f
Any other sort of instance and it's easy to run into problems with type
 inference.  If you want to write an instance that's "polymorphic" on
 tensor choice, use the WrapHBF and WrapF newtype wrappers over type
 variables, where the third argument also uses a type constructor:
instance MonoidIn (WrapHBF t) (WrapF i) (MyFunctor t i)
This will prevent problems with overloaded instances.
Minimal complete definition
Nothing
Methods
If we have an i, we can generate an f based on how it
 interacts with t.
Specialized (and simplified), this type is:
pureT@Day::Applicativef =>Identitya -> f a --purepureT @Comp::Monadf => Identity a -> f a --returnpureT @(:*:) ::Plusf =>Proxya -> f a --zero
Note that because t appears nowhere in the input or output types,
 you must always use this with explicit type application syntax (like
 pureT @Day)
Along with biretract, this function makes f a monoid in the
 category of endofunctors with respect to tensor t.
Instances
| Conclude f => MonoidIn Night Not f Source # | Instances of  | 
| Inplus f => MonoidIn Night Not f Source # | Since: 0.4.0.0 | 
| (Apply f, Applicative f) => MonoidIn Day Identity f Source # | Instances of  Note that because of typeclass constraints, this requires  | 
| Inplicative f => MonoidIn Day Identity f Source # | |
| (Divise f, Divisible f) => MonoidIn Day (Proxy :: Type -> Type) f Source # | Instances of  Note that because of typeclass constraints, this requires  Since: 0.3.0.0 | 
| Alt f => MonoidIn These1 (V1 :: Type -> Type) f Source # | |
| (Bind f, Monad f) => MonoidIn (Comp :: (Type -> Type) -> (Type -> Type) -> Type -> Type) Identity f Source # | Instances of  This instance is the "proof" that "monads are the monoids in the
 category of endofunctors (enriched with  Note that because of typeclass constraints, this requires  | 
| Plus f => MonoidIn (Product :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (Proxy :: Type -> Type) f Source # | Instances of  | 
| MonoidIn (Sum :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (V1 :: Type -> Type) f Source # | All functors are monoids in the monoidal category on  | 
| Plus f => MonoidIn ((:*:) :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (Proxy :: Type -> Type) f Source # | Instances of  | 
| MonoidIn ((:+:) :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (V1 :: Type -> Type) f Source # | All functors are monoids in the monoidal category on  | 
| (Tensor t i, FunctorBy t f, FunctorBy t (WrapLB t f)) => MonoidIn (WrapHBF t) (WrapF i) (WrapLB t f) Source # | |
| (Tensor t i, FunctorBy t (Chain t i f)) => MonoidIn (WrapHBF t) (WrapF i) (Chain t i f) Source # | 
 | 
nilLB :: forall t i f. Tensor t i => i ~> ListBy t f Source #
Create the "empty ListBy".
If ListBy t ft f with
 itself, then nilLB gives us "zero applications of f".
Note that t cannot be inferred from the input or output type of
 nilLB, so this function must always be called with -XTypeApplications:
nilLB@Day::Identity~>Apf nilLB @Comp:: Identity ~>Freef nilLB @(:*:) ::Proxy~>ListFf
Note that this essentially gives an instance for MonoidIn t i (ListBy
 t f)f; this is witnessed by WrapLB.
consLB :: Tensor t i => t f (ListBy t f) ~> ListBy t f Source #
Lets us "cons" an application of f to the front of an ListBy t f
Utility
inL :: forall t i f g. MonoidIn t i g => f ~> t f g Source #
Convenient wrapper over intro1 that lets us introduce an arbitrary
 functor g to the right of an f.
You can think of this as an HBifunctor analogue of inject.
inR :: forall t i f g. MonoidIn t i f => g ~> t f g Source #
Convenient wrapper over intro2 that lets us introduce an arbitrary
 functor f to the right of a g.
You can think of this as an HBifunctor analogue of inject.
A newtype wrapper meant to be used to define polymorphic MonoidIn
 instances.  See documentation for MonoidIn for more information.
Please do not ever define an instance of MonoidIn "naked" on the
 third parameter:
instance MonidIn (WrapHBF t) (WrapF i) f
As that would globally ruin everything using WrapHBF.
Instances
| Foldable f => Foldable (WrapF f) Source # | |
| Defined in Data.HBifunctor.Tensor Methods fold :: Monoid m => WrapF f m -> m # foldMap :: Monoid m => (a -> m) -> WrapF f a -> m # foldMap' :: Monoid m => (a -> m) -> WrapF f a -> m # foldr :: (a -> b -> b) -> b -> WrapF f a -> b # foldr' :: (a -> b -> b) -> b -> WrapF f a -> b # foldl :: (b -> a -> b) -> b -> WrapF f a -> b # foldl' :: (b -> a -> b) -> b -> WrapF f a -> b # foldr1 :: (a -> a -> a) -> WrapF f a -> a # foldl1 :: (a -> a -> a) -> WrapF f a -> a # elem :: Eq a => a -> WrapF f a -> Bool # maximum :: Ord a => WrapF f a -> a # minimum :: Ord a => WrapF f a -> a # | |
| Eq1 f => Eq1 (WrapF f) Source # | |
| Ord1 f => Ord1 (WrapF f) Source # | |
| Defined in Data.HBifunctor.Tensor | |
| Show1 f => Show1 (WrapF f) Source # | |
| Traversable f => Traversable (WrapF f) Source # | |
| Functor f => Functor (WrapF f) Source # | |
| (Typeable a, Typeable f, Typeable k, Data (f a)) => Data (WrapF f a) Source # | |
| Defined in Data.HBifunctor.Tensor Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> WrapF f a -> c (WrapF f a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (WrapF f a) # toConstr :: WrapF f a -> Constr # dataTypeOf :: WrapF f a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (WrapF f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (WrapF f a)) # gmapT :: (forall b. Data b => b -> b) -> WrapF f a -> WrapF f a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> WrapF f a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> WrapF f a -> r # gmapQ :: (forall d. Data d => d -> u) -> WrapF f a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> WrapF f a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> WrapF f a -> m (WrapF f a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> WrapF f a -> m (WrapF f a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> WrapF f a -> m (WrapF f a) # | |
| Generic (WrapF f a) Source # | |
| Read (f a) => Read (WrapF f a) Source # | |
| Show (f a) => Show (WrapF f a) Source # | |
| Eq (f a) => Eq (WrapF f a) Source # | |
| Ord (f a) => Ord (WrapF f a) Source # | |
| Tensor t i => Tensor (WrapHBF t) (WrapF i) Source # | |
| Defined in Data.HBifunctor.Tensor Methods intro1 :: forall (f :: Type -> Type). f ~> WrapHBF t f (WrapF i) Source # intro2 :: forall (g :: Type -> Type). g ~> WrapHBF t (WrapF i) g Source # elim1 :: forall (f :: Type -> Type). FunctorBy (WrapHBF t) f => WrapHBF t f (WrapF i) ~> f Source # elim2 :: forall (g :: Type -> Type). FunctorBy (WrapHBF t) g => WrapHBF t (WrapF i) g ~> g Source # appendLB :: forall (f :: Type -> Type). WrapHBF t (ListBy (WrapHBF t) f) (ListBy (WrapHBF t) f) ~> ListBy (WrapHBF t) f Source # splitNE :: forall (f :: Type -> Type). NonEmptyBy (WrapHBF t) f ~> WrapHBF t f (ListBy (WrapHBF t) f) Source # splittingLB :: forall (f :: Type -> Type). ListBy (WrapHBF t) f <~> (WrapF i :+: WrapHBF t f (ListBy (WrapHBF t) f)) Source # toListBy :: forall (f :: Type -> Type). WrapHBF t f f ~> ListBy (WrapHBF t) f Source # fromNE :: forall (f :: Type -> Type). NonEmptyBy (WrapHBF t) f ~> ListBy (WrapHBF t) f Source # | |
| (Tensor t i, FunctorBy t f, FunctorBy t (WrapLB t f)) => MonoidIn (WrapHBF t) (WrapF i) (WrapLB t f) Source # | |
| (Tensor t i, FunctorBy t (Chain t i f)) => MonoidIn (WrapHBF t) (WrapF i) (Chain t i f) Source # | 
 | 
| type Rep (WrapF f a) Source # | |
| Defined in Data.HBifunctor.Tensor | |
Any ListBy t fSemigroupIn tMonoidIn t iTensor t i
Instances
| Contravariant (ListBy t f) => Contravariant (WrapLB t f) Source # | Since: 0.3.0.0 | 
| Functor (ListBy t f) => Functor (WrapLB t f) Source # | |
| Invariant (ListBy t f) => Invariant (WrapLB t f) Source # | Since: 0.3.0.0 | 
| Defined in Data.HBifunctor.Tensor | |
| (Tensor t i, FunctorBy t f, FunctorBy t (WrapLB t f)) => SemigroupIn (WrapHBF t) (WrapLB t f) Source # | |
| (Tensor t i, FunctorBy t f, FunctorBy t (WrapLB t f)) => MonoidIn (WrapHBF t) (WrapF i) (WrapLB t f) Source # | |
Matchable
class Tensor t i => Matchable t i where Source #
For some t, we have the ability to "statically analyze" the ListBy tMatchable.
Methods
unsplitNE :: FunctorBy t f => t f (ListBy t f) ~> NonEmptyBy t f Source #
The inverse of splitNE.  A consing of f to ListBy t fNonEmptyBy t f
This is analogous to a function uncurry (:|)
 :: (a, [a]) -> NonEmpty a
matchLB :: FunctorBy t f => ListBy t f ~> (i :+: NonEmptyBy t f) Source #
"Pattern match" on an ListBy t fNonEmptyBy t f
This is analgous to a function nonEmpty :: [a]
 -> Maybe (NonEmpty a)
Note that because t cannot be inferred from the input or output
 type, you should use this with -XTypeApplications:
matchLB@Day::Apf a -> (Identity:+:Ap1f) a
Note that you can recursively "unroll" a ListBy completely into
 a Chain by using
 unrollLB.
Instances
| Matchable Night Not Source # | Since: 0.3.0.0 | 
| Matchable Night Not Source # | |
| Matchable Day Identity Source # | |
| Matchable Day Identity Source # | |
| Matchable Day (Proxy :: Type -> Type) Source # | Instances of  Since: 0.3.0.0 | 
| Matchable (Product :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (Proxy :: Type -> Type) Source # | |
| Matchable (Sum :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (V1 :: Type -> Type) Source # | |
| Matchable ((:*:) :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (Proxy :: Type -> Type) Source # | |
| Matchable ((:+:) :: (Type -> Type) -> (Type -> Type) -> Type -> Type) (V1 :: Type -> Type) Source # | |
splittingNE :: (Matchable t i, FunctorBy t f) => NonEmptyBy t f <~> t f (ListBy t f) Source #
An NonEmptyBy t ff consed with an ListBy t fNonEmpty a(a, [a]).
matchingLB :: forall t i f. (Matchable t i, FunctorBy t f) => ListBy t f <~> (i :+: NonEmptyBy t f) Source #
An ListBy t fi) or the
 non-empty case (NonEmptyBy t f[a] is isomorphic to Maybe
 (NonEmpty a)