-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Tools for functor combinator-based program design -- -- Tools for working with functor combinators: types that take -- functors (or other indexed types) and returns a new functor that -- "enhances" or "mixes" them in some way. In the process, you can design -- featureful programs by composing smaller "primitives" using basic -- unversal combinators. -- -- The main entry point is Data.Functor.Combinators, but more -- fine-grained functionality and extra combinators (some of them -- re-implementations for compatibility) are available in other modules -- as well. -- -- This library does not define new functor combinators for the most -- part, but rather re-exports them from different parts of the Haskell -- ecosystem and provides a uniform interface. -- -- See the README for a quick overview, and also -- https://blog.jle.im/entry/functor-combinatorpedia.html for an -- in-depth dive into the motivation behind functor combinator-driven -- development, examples of the functor combinators in this library, and -- details about how to use these abstractions! @package functor-combinators @version 0.1.1.0 -- | This module provides functor combinators that are wrappers over lists -- or maybes of f as, especially for their Interpret -- instances. -- -- Each one transforms a functor into some product of itself. For -- example, NonEmptyF f represents f :*: -- f, or f :*: f :*: f, or f :*: f :*: f :*: f, -- etc. module Control.Applicative.ListF -- | A list of f as. Can be used to describe a product of many -- different values of type f a. -- -- This is the Free Plus. newtype ListF f a ListF :: [f a] -> ListF f a [runListF] :: ListF f a -> [f a] -- | Map a function over the inside of a ListF. mapListF :: ([f a] -> [g b]) -> ListF f a -> ListF g b -- | A non-empty list of f as. Can be used to describe a product -- between many different possible values of type f a. -- -- Essentially: -- --
-- NonEmptyF f -- ~ f -- one f -- :+: (f :*: f) -- two f's -- :+: (f :*: f :*: f) -- three f's -- :+: (f :*: f :*: f :*: f) -- four f's -- :+: ... -- etc. ---- -- This is the Free Plus. newtype NonEmptyF f a NonEmptyF :: NonEmpty (f a) -> NonEmptyF f a [runNonEmptyF] :: NonEmptyF f a -> NonEmpty (f a) -- | Map a function over the inside of a NonEmptyF. mapNonEmptyF :: (NonEmpty (f a) -> NonEmpty (g b)) -> NonEmptyF f a -> NonEmptyF g b -- | Convert a NonEmptyF into a ListF with at least one item. toListF :: NonEmptyF f ~> ListF f -- | Convert a ListF either a NonEmptyF, or a Proxy in -- the case that the list was empty. fromListF :: ListF f ~> (Proxy :+: NonEmptyF f) -- | A maybe f a. -- -- Can be useful for describing a "an f a that may or may not be -- there". -- -- This is the free structure for a "fail"-like typeclass that would only -- have zero :: f a. newtype MaybeF f a MaybeF :: Maybe (f a) -> MaybeF f a [runMaybeF] :: MaybeF f a -> Maybe (f a) -- | Map a function over the inside of a MaybeF. mapMaybeF :: (Maybe (f a) -> Maybe (g b)) -> MaybeF f a -> MaybeF g b -- | Convert a ListF into a MaybeF containing the first f -- a in the list, if it exists. listToMaybeF :: ListF f ~> MaybeF f -- | Convert a MaybeF into a ListF with zero or one items. maybeToListF :: MaybeF f ~> ListF f -- | A map of f as, indexed by keys of type k. It can be -- useful for represeting a product of many different values of type -- f a, each "at" a different k location. -- -- Can be considered a combination of EnvT and ListF, in a -- way --- a MapF k f a is like a ListF -- (EnvT k f) a with unique (and ordered) keys. -- -- One use case might be to extend a schema with many "options", indexed -- by some string. -- -- For example, if you had a command line argument parser for a single -- command -- --
-- data Command a ---- -- Then you can represent a command line argument parser for -- multiple named commands with -- --
-- type Commands = MapF String Command ---- -- See NEMapF for a non-empty variant, if you want to enforce that -- your bag has at least one f a. newtype MapF k f a MapF :: Map k (f a) -> MapF k f a [runMapF] :: MapF k f a -> Map k (f a) -- | A non-empty map of f as, indexed by keys of type k. -- It can be useful for represeting a product of many different values of -- type f a, each "at" a different k location, where -- you need to have at least one f a at all times. -- -- Can be considered a combination of EnvT and NonEmptyF, -- in a way --- an NEMapF k f a is like a -- NonEmptyF (EnvT k f) a with unique (and -- ordered) keys. -- -- See MapF for some use cases. newtype NEMapF k f a NEMapF :: NEMap k (f a) -> NEMapF k f a [runNEMapF] :: NEMapF k f a -> NEMap k (f a) instance (GHC.Classes.Ord k, Data.Functor.Classes.Ord1 f) => Data.Functor.Classes.Ord1 (Control.Applicative.ListF.NEMapF k f) instance (GHC.Classes.Ord k, GHC.Read.Read k, Data.Functor.Classes.Read1 f) => Data.Functor.Classes.Read1 (Control.Applicative.ListF.NEMapF k f) instance Data.Semigroup.Foldable.Class.Foldable1 f => Data.Semigroup.Foldable.Class.Foldable1 (Control.Applicative.ListF.NEMapF k f) instance Data.Semigroup.Traversable.Class.Traversable1 f => Data.Semigroup.Traversable.Class.Traversable1 (Control.Applicative.ListF.NEMapF k f) instance (GHC.Classes.Ord k, Data.Functor.Alt.Alt f) => GHC.Base.Semigroup (Control.Applicative.ListF.NEMapF k f a) instance (GHC.Base.Functor f, GHC.Classes.Ord k) => Data.Functor.Alt.Alt (Control.Applicative.ListF.NEMapF k f) instance (GHC.Base.Monoid k, Data.Pointed.Pointed f) => Data.Pointed.Pointed (Control.Applicative.ListF.NEMapF k f) instance (GHC.Classes.Eq k, Data.Functor.Classes.Eq1 f) => Data.Functor.Classes.Eq1 (Control.Applicative.ListF.NEMapF k f) instance (GHC.Show.Show k, Data.Functor.Classes.Show1 f) => Data.Functor.Classes.Show1 (Control.Applicative.ListF.NEMapF k f) instance (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Data.Data k, Data.Data.Data (f a), GHC.Classes.Ord k) => Data.Data.Data (Control.Applicative.ListF.NEMapF k f a) instance GHC.Generics.Generic (Control.Applicative.ListF.NEMapF k f a) instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Control.Applicative.ListF.NEMapF k f) instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Control.Applicative.ListF.NEMapF k f) instance GHC.Base.Functor f => GHC.Base.Functor (Control.Applicative.ListF.NEMapF k f) instance (GHC.Classes.Ord k, GHC.Classes.Ord (f a)) => GHC.Classes.Ord (Control.Applicative.ListF.NEMapF k f a) instance (GHC.Classes.Eq k, GHC.Classes.Eq (f a)) => GHC.Classes.Eq (Control.Applicative.ListF.NEMapF k f a) instance (GHC.Classes.Ord k, GHC.Read.Read k, GHC.Read.Read (f a)) => GHC.Read.Read (Control.Applicative.ListF.NEMapF k f a) instance (GHC.Show.Show k, GHC.Show.Show (f a)) => GHC.Show.Show (Control.Applicative.ListF.NEMapF k f a) instance (GHC.Classes.Ord k, Data.Functor.Classes.Ord1 f) => Data.Functor.Classes.Ord1 (Control.Applicative.ListF.MapF k f) instance (GHC.Classes.Ord k, GHC.Read.Read k, Data.Functor.Classes.Read1 f) => Data.Functor.Classes.Read1 (Control.Applicative.ListF.MapF k f) instance (GHC.Classes.Ord k, Data.Functor.Alt.Alt f) => GHC.Base.Semigroup (Control.Applicative.ListF.MapF k f a) instance (GHC.Classes.Ord k, Data.Functor.Alt.Alt f) => GHC.Base.Monoid (Control.Applicative.ListF.MapF k f a) instance (GHC.Base.Functor f, GHC.Classes.Ord k) => Data.Functor.Alt.Alt (Control.Applicative.ListF.MapF k f) instance (GHC.Base.Functor f, GHC.Classes.Ord k) => Data.Functor.Plus.Plus (Control.Applicative.ListF.MapF k f) instance (GHC.Base.Monoid k, Data.Pointed.Pointed f) => Data.Pointed.Pointed (Control.Applicative.ListF.MapF k f) instance (GHC.Classes.Eq k, Data.Functor.Classes.Eq1 f) => Data.Functor.Classes.Eq1 (Control.Applicative.ListF.MapF k f) instance (GHC.Show.Show k, Data.Functor.Classes.Show1 f) => Data.Functor.Classes.Show1 (Control.Applicative.ListF.MapF k f) instance (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Data.Data k, Data.Data.Data (f a), GHC.Classes.Ord k) => Data.Data.Data (Control.Applicative.ListF.MapF k f a) instance GHC.Generics.Generic (Control.Applicative.ListF.MapF k f a) instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Control.Applicative.ListF.MapF k f) instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Control.Applicative.ListF.MapF k f) instance GHC.Base.Functor f => GHC.Base.Functor (Control.Applicative.ListF.MapF k f) instance (GHC.Classes.Ord k, GHC.Classes.Ord (f a)) => GHC.Classes.Ord (Control.Applicative.ListF.MapF k f a) instance (GHC.Classes.Eq k, GHC.Classes.Eq (f a)) => GHC.Classes.Eq (Control.Applicative.ListF.MapF k f a) instance (GHC.Classes.Ord k, GHC.Read.Read k, GHC.Read.Read (f a)) => GHC.Read.Read (Control.Applicative.ListF.MapF k f a) instance (GHC.Show.Show k, GHC.Show.Show (f a)) => GHC.Show.Show (Control.Applicative.ListF.MapF k f a) instance Data.Functor.Classes.Ord1 f => Data.Functor.Classes.Ord1 (Control.Applicative.ListF.MaybeF f) instance GHC.Base.Applicative f => GHC.Base.Applicative (Control.Applicative.ListF.MaybeF f) instance GHC.Base.Functor f => Data.Functor.Alt.Alt (Control.Applicative.ListF.MaybeF f) instance GHC.Base.Functor f => Data.Functor.Plus.Plus (Control.Applicative.ListF.MaybeF f) instance GHC.Base.Applicative f => GHC.Base.Alternative (Control.Applicative.ListF.MaybeF f) instance GHC.Base.Semigroup (Control.Applicative.ListF.MaybeF f a) instance GHC.Base.Monoid (Control.Applicative.ListF.MaybeF f a) instance Data.Pointed.Pointed f => Data.Pointed.Pointed (Control.Applicative.ListF.MaybeF f) instance Data.Functor.Classes.Eq1 f => Data.Functor.Classes.Eq1 (Control.Applicative.ListF.MaybeF f) instance Data.Functor.Classes.Read1 f => Data.Functor.Classes.Read1 (Control.Applicative.ListF.MaybeF f) instance Data.Functor.Classes.Show1 f => Data.Functor.Classes.Show1 (Control.Applicative.ListF.MaybeF f) instance (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Data.Data (f a)) => Data.Data.Data (Control.Applicative.ListF.MaybeF f a) instance GHC.Generics.Generic (Control.Applicative.ListF.MaybeF f a) instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Control.Applicative.ListF.MaybeF f) instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Control.Applicative.ListF.MaybeF f) instance GHC.Base.Functor f => GHC.Base.Functor (Control.Applicative.ListF.MaybeF f) instance GHC.Classes.Ord (f a) => GHC.Classes.Ord (Control.Applicative.ListF.MaybeF f a) instance GHC.Classes.Eq (f a) => GHC.Classes.Eq (Control.Applicative.ListF.MaybeF f a) instance GHC.Read.Read (f a) => GHC.Read.Read (Control.Applicative.ListF.MaybeF f a) instance GHC.Show.Show (f a) => GHC.Show.Show (Control.Applicative.ListF.MaybeF f a) instance Data.Functor.Classes.Ord1 f => Data.Functor.Classes.Ord1 (Control.Applicative.ListF.NonEmptyF f) instance GHC.Base.Applicative f => GHC.Base.Applicative (Control.Applicative.ListF.NonEmptyF f) instance GHC.Base.Functor f => Data.Functor.Alt.Alt (Control.Applicative.ListF.NonEmptyF f) instance GHC.Base.Semigroup (Control.Applicative.ListF.NonEmptyF f a) instance Data.Pointed.Pointed f => Data.Pointed.Pointed (Control.Applicative.ListF.NonEmptyF f) instance Data.Functor.Classes.Eq1 f => Data.Functor.Classes.Eq1 (Control.Applicative.ListF.NonEmptyF f) instance Data.Functor.Classes.Read1 f => Data.Functor.Classes.Read1 (Control.Applicative.ListF.NonEmptyF f) instance Data.Functor.Classes.Show1 f => Data.Functor.Classes.Show1 (Control.Applicative.ListF.NonEmptyF f) instance (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Data.Data (f a)) => Data.Data.Data (Control.Applicative.ListF.NonEmptyF f a) instance GHC.Generics.Generic (Control.Applicative.ListF.NonEmptyF f a) instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Control.Applicative.ListF.NonEmptyF f) instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Control.Applicative.ListF.NonEmptyF f) instance GHC.Base.Functor f => GHC.Base.Functor (Control.Applicative.ListF.NonEmptyF f) instance GHC.Classes.Ord (f a) => GHC.Classes.Ord (Control.Applicative.ListF.NonEmptyF f a) instance GHC.Classes.Eq (f a) => GHC.Classes.Eq (Control.Applicative.ListF.NonEmptyF f a) instance GHC.Read.Read (f a) => GHC.Read.Read (Control.Applicative.ListF.NonEmptyF f a) instance GHC.Show.Show (f a) => GHC.Show.Show (Control.Applicative.ListF.NonEmptyF f a) instance Data.Functor.Classes.Ord1 f => Data.Functor.Classes.Ord1 (Control.Applicative.ListF.ListF f) instance Data.Functor.Bind.Class.Apply f => Data.Functor.Bind.Class.Apply (Control.Applicative.ListF.ListF f) instance GHC.Base.Applicative f => GHC.Base.Applicative (Control.Applicative.ListF.ListF f) instance GHC.Base.Functor f => Data.Functor.Alt.Alt (Control.Applicative.ListF.ListF f) instance GHC.Base.Functor f => Data.Functor.Plus.Plus (Control.Applicative.ListF.ListF f) instance GHC.Base.Applicative f => GHC.Base.Alternative (Control.Applicative.ListF.ListF f) instance GHC.Base.Semigroup (Control.Applicative.ListF.ListF f a) instance GHC.Base.Monoid (Control.Applicative.ListF.ListF f a) instance Data.Pointed.Pointed f => Data.Pointed.Pointed (Control.Applicative.ListF.ListF f) instance Data.Functor.Classes.Eq1 f => Data.Functor.Classes.Eq1 (Control.Applicative.ListF.ListF f) instance Data.Functor.Classes.Read1 f => Data.Functor.Classes.Read1 (Control.Applicative.ListF.ListF f) instance Data.Functor.Classes.Show1 f => Data.Functor.Classes.Show1 (Control.Applicative.ListF.ListF f) instance (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Data.Data (f a)) => Data.Data.Data (Control.Applicative.ListF.ListF f a) instance GHC.Generics.Generic (Control.Applicative.ListF.ListF f a) instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Control.Applicative.ListF.ListF f) instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Control.Applicative.ListF.ListF f) instance GHC.Base.Functor f => GHC.Base.Functor (Control.Applicative.ListF.ListF f) instance GHC.Classes.Ord (f a) => GHC.Classes.Ord (Control.Applicative.ListF.ListF f a) instance GHC.Classes.Eq (f a) => GHC.Classes.Eq (Control.Applicative.ListF.ListF f a) instance GHC.Read.Read (f a) => GHC.Read.Read (Control.Applicative.ListF.ListF f a) instance GHC.Show.Show (f a) => GHC.Show.Show (Control.Applicative.ListF.ListF f a) -- | The church-encoded Freer Monad. Basically provides the free -- monad in a way that is compatible with HFunctor and -- Interpret. We also have the "semigroup" version Free1, -- which is the free Bind. -- -- The module also provides a version of :.: (or Compose), -- Comp, in a way that is compatible with HBifunctor and -- the related typeclasses. module Control.Monad.Freer.Church -- | A Free f is f enhanced with "sequential -- binding" capabilities. It allows you to sequence multiple fs -- one after the other, and also to determine "what f to -- sequence" based on the result of the computation so far. -- -- Essentially, you can think of this as "giving f a -- Monad instance", with all that that entails (return, -- >>=, etc.). -- -- Lift f into it with inject :: f a -> Free f -- a. When you finally want to "use" it, you can interpret it into -- any monadic context: -- --
-- interpret -- :: Monad g -- => (forall x. f x -> g x) -- -> Free f a -- -> g a ---- -- Structurally, this is equivalent to many "nested" f's. A value of type -- Free f a is either: -- --
a
f a
f (f a)
f (f (f a))
-- viewF :: (f <~> g) -> f a -> g a -- reviewF :: (f <~> g) -> g a -> a a ---- -- Use viewF to extract the "f to g" function, -- and reviewF to extract the "g to f" function. -- Reviewing and viewing the same value (or vice versa) leaves the value -- unchanged. -- -- One nice thing is that we can compose isomorphisms using . from -- Prelude: -- --
-- (.) :: f <~> g -- -> g <~> h -- -> f <~> h ---- -- Another nice thing about this representation is that we have the -- "identity" isomorphism by using id from Prelude. -- --
-- id :: f <~> g ---- -- As a convention, most isomorphisms have form "X-ing", where the -- forwards function is "ing". For example, we have: -- --
-- splittingSF :: Monoidal t => SF t a <~> t f (MF t f) -- splitSF :: Monoidal t => SF t a ~> t f (MF t f) --type f <~> g = forall p a. Profunctor p => p (g a) (g a) -> p (f a) (f a) infixr 0 <~> -- | Create an f <~> g by providing both legs of the -- isomorphism (the f a -> g a and the g a -> f -- a. isoF :: (f ~> g) -> (g ~> f) -> f <~> g -- | Use a <~> by retrieving the "forward" function: -- --
-- viewF :: (f ~ g) -> f a -> g a --viewF :: (f <~> g) -> f ~> g -- | Use a <~> by retrieving the "backwards" function: -- --
-- viewF :: (f ~ g) -> f a -> g a --reviewF :: (f <~> g) -> g ~> f -- | Lift a function g a ~> g a to be a function f a -> -- f a, given an isomorphism between the two. -- -- One neat thing is that overF i id == id. overF :: (f <~> g) -> (g ~> g) -> f ~> f -- | Reverse an isomorphism. -- --
-- viewF (fromF i) == reviewF i -- reviewF (fromF i) == viewF i --fromF :: (f <~> g) -> g <~> f -- | Profunctor that allows us to implement fromF. data Exchange a b s t Exchange :: (s -> a) -> (b -> t) -> Exchange a b s t instance GHC.Base.Functor (Control.Natural.IsoF.Exchange a b s) instance Data.Profunctor.Unsafe.Profunctor (Control.Natural.IsoF.Exchange a b) -- | This module provides functor combinators that are the fixed points of -- applications of :+: and These1. They are useful for -- their Interpret instances, along with their relationship to the -- Monoidal instances of :+: and These1. module Control.Applicative.Step -- | An f a, along with a Natural index. -- --
-- Step f a ~ (Natural, f a) -- Step f ~ ((,) Natural) :.: f -- functor composition ---- -- It is the fixed point of infinite applications of :+: (functor -- sums). -- -- Intuitively, in an infinite f :+: f :+: f :+: f ..., you have -- exactly one f somewhere. A Step f a -- has that f, with a Natural giving you "where" the -- f is in the long chain. -- -- Can be useful for using with the Monoidal instance of -- :+:. -- -- interpreting it requires no constraint on the target context. -- -- Note that this type and its instances equivalent to EnvT -- (Sum Natural). data Step f a Step :: Natural -> f a -> Step f a [stepPos] :: Step f a -> Natural [stepVal] :: Step f a -> f a -- | A non-empty map of Natural to f a. Basically, contains -- multiple f as, each at a given Natural index. -- --
-- Steps f a ~ Map Natural (f a) -- Steps f ~ Map Natural :.: f -- functor composition ---- -- It is the fixed point of applications of TheseT. -- -- You can think of this as an infinite sparse array of f as. -- -- Intuitively, in an infinite f `TheseT` f `TheseT` f `TheseT` f -- ..., each of those infinite positions may have an f in -- them. However, because of the at-least-one nature of TheseT, we -- know we have at least one f at one position somewhere. -- -- A Steps f a has potentially many fs, each -- stored at a different Natural position, with the guaruntee that -- at least one f exists. -- -- Can be useful for using with the Monoidal instance of -- TheseT. -- -- interpreting it requires at least an Alt instance in the -- target context, since we have to handle potentially more than one -- f. -- -- This type is essentailly the same as NEMapF (Sum -- Natural) (except with a different Semigroup -- instance). newtype Steps f a Steps :: NEMap Natural (f a) -> Steps f a [getSteps] :: Steps f a -> NEMap Natural (f a) -- | An f a, along with a Bool flag -- --
-- Flagged f a ~ (Bool, f a) -- Flagged f ~ ((,) Bool) :.: f -- functor composition ---- -- Creation with inject or pure uses False as the -- boolean. -- -- You can think of it as an f a that is "flagged" with a -- boolean value, and that value can indicuate whether or not it is -- "pure" (made with inject or pure) as False, or -- "impure" (made from some other source) as True. However, -- False may be always created directly, of course, using the -- constructor. -- -- You can think of it like a Step that is either 0 or 1, as well. -- -- interpreting it requires no constraint on the target context. -- -- This type is equivalent (along with its instances) to: -- -- data Flagged f a Flagged :: Bool -> f a -> Flagged f a [flaggedFlag] :: Flagged f a -> Bool [flaggedVal] :: Flagged f a -> f a -- | Unshift an item into a Step. Because a Step f -- is f :+: f :+: f :+: f :+: ... forever, this basically conses -- an additional possibility of f to the beginning of it all. -- -- You can think of it as reassociating -- --
-- f :+: ( f :+: f :+: f :+: ...) ---- -- into -- --
-- f :+: f :+: f :+: f :+: ... ---- --
-- stepUp (L1 "hello") -- -- Step 0 "hello" -- stepUp (R1 (Step 1 "hello")) -- -- Step 2 "hello" ---- -- Forms an isomorphism with stepDown (see stepping). stepUp :: (f :+: Step f) ~> Step f -- | Pop off the first item in a Step. Because a Step -- f is f :+: f :+: f :+: ... forever, this matches on the -- first branch. -- -- You can think of it as reassociating -- --
-- f :+: f :+: f :+: f :+: ... ---- -- into -- --
-- f :+: ( f :+: f :+: f :+: ...) ---- --
-- stepDown (Step 2 "hello") -- -- R1 (Step 1 "hello") -- stepDown (Step 0 "hello") -- -- L1 "hello" ---- -- Forms an isomorphism with stepUp (see stepping). stepDown :: Step f ~> (f :+: Step f) -- | "Uncons and cons" an f branch before a Step. This is -- basically a witness that stepDown and stepUp form an -- isomorphism. stepping :: Step f <~> (f :+: Step f) -- | Unshift an item into a Steps. Because a Steps f -- is f These1 f These1 f These1 f These1 -- ... forever, this basically conses an additional possibility of -- f to the beginning of it all. -- -- You can think of it as reassociating -- --
-- f These1 ( f These1 f These1 f These1 ...) ---- -- into -- --
-- f These1 f These1 f These1 f These1 ... ---- -- If you give: -- --
-- f These1 f These1 f These1 f These1 ... ---- -- into -- --
-- f These1 ( f These1 f These1 f These1 ...) ---- -- It returns: -- --
-- hmap id == id ---- -- Essentially, t f adds some "extra structure" to f. -- hmap must swap out the functor, without affecting the added -- structure. -- -- For example, ListF f a is essentially a list of f -- as. If we hmap to swap out the f as for g -- as, then we must ensure that the "added structure" (here, the -- number of items in the list, and the ordering of those items) remains -- the same. So, hmap must preserve the number of items in the -- list, and must maintain the ordering. -- -- The law hmap id == id is a way of formalizing -- this property. hmap :: HFunctor t => (f ~> g) -> t f ~> t g -- | Lift an isomorphism over an HFunctor. -- -- Essentailly, if f and g are isomorphic, then so are -- t f and t g. overHFunctor :: HFunctor t => (f <~> g) -> t f <~> t g -- | A typeclass for HFunctors where you can "inject" an f -- a into a t f a: -- --
-- inject :: f a -> t f a ---- -- If you think of t f a as an "enhanced f", then -- inject allows you to use an f as its enhanced form. -- -- With the exception of directly pattern matching on the result, -- inject itself is not too useful in the general case without -- Interpret to allow us to interpret or retrieve back the -- f. class HFunctor t => Inject t -- | Lift from f into the enhanced t f structure. -- Analogous to lift from MonadTrans. -- -- Note that this lets us "lift" a f a; if you want to lift an -- a with a -> t f a, check if t f is an -- instance of Applicative or Pointed. inject :: Inject t => f ~> t f -- | HBind is effectively a "higher-order Monad", in the -- sense that HFunctor is a "higher-order Functor". -- -- It can be considered a typeclass for HFunctors that you can -- bind continuations to, nautraluniversal over all -- ffunctors. They work "for all functors" you lift, without -- requiring any constraints. -- -- It is very similar to Interpret, except Interpret has -- the ability to constrain the contexts to some typeclass. -- -- The main law is that binding inject should leave things -- unchanged: -- --
-- hbind inject == id ---- -- But hbind should also be associatiatve, in a way that makes -- --
-- hjoin . hjoin -- = hjoin . hmap hjoin ---- -- That is, squishing a t (t (t f)) a into a t f a can -- be done "inside" first, then "outside", or "outside" first, then -- "inside". -- -- Note that these laws are different from the Interpret laws, so -- we often have instances where hbind and interpret -- (though they both may typecheck) produce different behavior. -- -- This class is similar to MMonad from -- Control.Monad.Morph, but instances must work without a -- Monad constraint. class Inject t => HBind t -- | Bind a continuation to a t f into some context g. hbind :: HBind t => (f ~> t g) -> t f ~> t g -- | Collapse a nested t (t f) into a single t f. hjoin :: HBind t => t (t f) ~> t f -- | The functor combinator that forgets all structure in the input. -- Ignores the input structure and stores no information. -- -- Acts like the "zero" with respect to functor combinator composition. -- --
-- ComposeT ProxyF f ~ ProxyF -- ComposeT f ProxyF ~ ProxyF ---- -- It can be injected into (losing all information), but it is -- impossible to ever retract or interpret it. -- -- This is essentially ConstF (). data ProxyF f a ProxyF :: ProxyF f a -- | Functor combinator that forgets all structure on the input, and -- instead stores a value of type e. -- -- Like ProxyF, acts like a "zero" with functor combinator -- composition. -- -- It can be injected into (losing all information), but it is -- impossible to ever retract or interpret it. data ConstF e f a ConstF :: e -> ConstF e f a [getConstF] :: ConstF e f a -> e -- | An "HFunctor combinator" that enhances an HFunctor with -- the ability to hold a single f a. This is the higher-order -- analogue of Lift. -- -- You can think of it as a free Inject for any f. -- -- Note that HLift IdentityT is equivalent to -- EnvT Any. data HLift t f a HPure :: f a -> HLift t f a HOther :: t f a -> HLift t f a -- | A higher-level retract to get a t f a back out of an -- HLift t f a, provided t is an instance of -- Inject. -- -- This witnesses the fact that HLift is the "Free Inject". retractHLift :: Inject t => HLift t f a -> t f a -- | An "HFunctor combinator" that turns an HFunctor into -- potentially infinite nestings of that HFunctor. -- -- An HFree t f a is either f a, t f a, -- t (t f) a, t (t (t f)) a, etc. -- -- This effectively turns t into a tree with t -- branches. -- -- One particularly useful usage is with MapF. For example if you -- had a data type representing a command line command parser: -- --
-- data Command a ---- -- You could represent "many possible named commands" using -- --
-- type Commands = MapF String Command ---- -- And you can represent multiple nested named commands using: -- --
-- type NestedCommands = HFree (MapF String) ---- -- This has an Interpret instance, but it can be more useful to -- use via direct pattern matching, or through -- --
-- foldHFree -- :: HBifunctor t -- => f ~> g -- -> t g ~> g -- -> HFree t f ~> g ---- -- which requires no extra constriant on g, and lets you -- consider each branch separately. -- -- This can be considered the higher-oder analogue of Free; it is -- the free HBind for any HFunctor t. -- -- Note that HFree IdentityT is equivalent to -- Step. data HFree t f a HReturn :: f a -> HFree t f a HJoin :: t (HFree t f) a -> HFree t f a -- | Recursively fold down an HFree into a single g result, -- by handling each branch. Can be more useful than interpret -- because it allows you to treat each branch separately, and also does -- not require any constraint on g. -- -- This is the catamorphism on HFree. foldHFree :: forall t f g. HFunctor t => (f ~> g) -> (t g ~> g) -> HFree t f ~> g -- | A higher-level retract to get a t f a back out of an -- HFree t f a, provided t is an instance of -- Bind. -- -- This witnesses the fact that HFree is the "Free Bind". retractHFree :: HBind t => HFree t f a -> t f a instance (GHC.Base.Functor f, GHC.Base.Functor (t f)) => GHC.Base.Functor (Data.HFunctor.HLift t f) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> k -> *). (GHC.Show.Show (f a), GHC.Show.Show (t f a)) => GHC.Show.Show (Data.HFunctor.HLift t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> k -> *). (GHC.Read.Read (f a), GHC.Read.Read (t f a)) => GHC.Read.Read (Data.HFunctor.HLift t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> k -> *). (GHC.Classes.Eq (f a), GHC.Classes.Eq (t f a)) => GHC.Classes.Eq (Data.HFunctor.HLift t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> k -> *). (GHC.Classes.Ord (f a), GHC.Classes.Ord (t f a)) => GHC.Classes.Ord (Data.HFunctor.HLift t f a) instance (GHC.Base.Functor f, GHC.Base.Functor (t (Data.HFunctor.HFree t f))) => GHC.Base.Functor (Data.HFunctor.HFree t f) instance Data.HFunctor.HBind Data.Functor.Coyoneda.Coyoneda instance Data.HFunctor.HBind Control.Applicative.Free.Ap instance Data.HFunctor.HBind Control.Applicative.ListF.ListF instance Data.HFunctor.HBind Control.Applicative.ListF.NonEmptyF instance Data.HFunctor.HBind Control.Applicative.ListF.MaybeF instance Data.HFunctor.HBind Control.Applicative.Step.Step instance Data.HFunctor.HBind Control.Applicative.Step.Flagged instance Data.Functor.Alt.Alt f => Data.HFunctor.HBind (Data.Functor.These.These1 f) instance Data.Functor.Plus.Plus f => Data.HFunctor.HBind ((GHC.Generics.:*:) f) instance Data.Functor.Plus.Plus f => Data.HFunctor.HBind (Data.Functor.Product.Product f) instance forall k (f :: k -> *). Data.HFunctor.HBind ((GHC.Generics.:+:) f) instance forall k (f :: k -> *). Data.HFunctor.HBind (Data.Functor.Sum.Sum f) instance Data.HFunctor.HBind (GHC.Generics.M1 i c) instance Data.HFunctor.HBind Control.Alternative.Free.Alt instance Data.HFunctor.HBind Control.Monad.Freer.Church.Free instance Data.HFunctor.HBind Control.Monad.Freer.Church.Free1 instance Data.HFunctor.HBind Control.Applicative.Free.Final.Ap instance Data.HFunctor.HBind Control.Applicative.Free.Fast.Ap instance Data.HFunctor.HBind Control.Monad.Trans.Identity.IdentityT instance Data.HFunctor.HBind Control.Applicative.Lift.Lift instance Data.HFunctor.HBind Data.Functor.Bind.Class.MaybeApply instance Data.HFunctor.HBind Control.Applicative.Backwards.Backwards instance Data.HFunctor.HBind Data.Functor.Bind.Class.WrappedApplicative instance Data.HFunctor.HBind Data.Functor.Reverse.Reverse instance Data.HFunctor.HBind Data.HFunctor.ProxyF instance GHC.Base.Monoid e => Data.HFunctor.HBind (Control.Comonad.Trans.Env.EnvT e) instance forall k (t :: (k -> *) -> k -> *). (Data.HFunctor.HBind t, Data.HFunctor.Inject t) => Data.HFunctor.HBind (Data.HFunctor.HLift t) instance forall k (t :: (k -> *) -> k -> *). Data.HFunctor.Internal.HFunctor t => Data.HFunctor.HBind (Data.HFunctor.HFree t) instance Data.HFunctor.Inject Data.Functor.Coyoneda.Coyoneda instance Data.HFunctor.Inject Control.Applicative.Free.Ap instance Data.HFunctor.Inject Control.Applicative.ListF.ListF instance Data.HFunctor.Inject Control.Applicative.ListF.NonEmptyF instance Data.HFunctor.Inject Control.Applicative.ListF.MaybeF instance GHC.Base.Monoid k => Data.HFunctor.Inject (Control.Applicative.ListF.NEMapF k) instance GHC.Base.Monoid k => Data.HFunctor.Inject (Control.Applicative.ListF.MapF k) instance Data.HFunctor.Inject Control.Applicative.Step.Step instance Data.HFunctor.Inject Control.Applicative.Step.Steps instance Data.HFunctor.Inject Control.Applicative.Step.Flagged instance Data.HFunctor.Inject (Data.Functor.These.These1 f) instance GHC.Base.Applicative f => Data.HFunctor.Inject (Control.Monad.Freer.Church.Comp f) instance GHC.Base.Applicative f => Data.HFunctor.Inject ((GHC.Generics.:.:) f) instance Data.Functor.Plus.Plus f => Data.HFunctor.Inject ((GHC.Generics.:*:) f) instance Data.Functor.Plus.Plus f => Data.HFunctor.Inject (Data.Functor.Product.Product f) instance forall k (f :: k -> *). Data.HFunctor.Inject ((GHC.Generics.:+:) f) instance forall k (f :: k -> *). Data.HFunctor.Inject (Data.Functor.Sum.Sum f) instance Data.HFunctor.Inject (GHC.Generics.M1 i c) instance Data.HFunctor.Inject Control.Alternative.Free.Alt instance Data.HFunctor.Inject Control.Monad.Freer.Church.Free instance Data.HFunctor.Inject Control.Monad.Freer.Church.Free1 instance Data.HFunctor.Inject Control.Applicative.Free.Final.Ap instance Data.HFunctor.Inject Control.Applicative.Free.Fast.Ap instance Data.HFunctor.Inject Control.Monad.Trans.Identity.IdentityT instance Data.HFunctor.Inject Control.Applicative.Lift.Lift instance Data.HFunctor.Inject Data.Functor.Bind.Class.MaybeApply instance Data.HFunctor.Inject Control.Applicative.Backwards.Backwards instance Data.HFunctor.Inject Data.Functor.Bind.Class.WrappedApplicative instance Data.HFunctor.Inject (Control.Monad.Trans.Reader.ReaderT r) instance GHC.Base.Monoid e => Data.HFunctor.Inject (Control.Comonad.Trans.Env.EnvT e) instance Data.HFunctor.Inject Data.Functor.Reverse.Reverse instance Data.HFunctor.Inject Data.HFunctor.ProxyF instance GHC.Base.Monoid e => Data.HFunctor.Inject (Data.HFunctor.ConstF e) instance (Data.HFunctor.Inject s, Data.HFunctor.Inject t) => Data.HFunctor.Inject (Control.Monad.Trans.Compose.ComposeT s t) instance forall k (t :: (k -> *) -> k -> *). Data.HFunctor.Internal.HFunctor t => Data.HFunctor.Inject (Data.HFunctor.HLift t) instance forall k (t :: (k -> *) -> k -> *). Data.HFunctor.Internal.HFunctor t => Data.HFunctor.Inject (Data.HFunctor.HFree t) instance (Data.Functor.Classes.Show1 (t (Data.HFunctor.HFree t f)), Data.Functor.Classes.Show1 f) => Data.Functor.Classes.Show1 (Data.HFunctor.HFree t f) instance (Data.Functor.Classes.Show1 (t (Data.HFunctor.HFree t f)), Data.Functor.Classes.Show1 f, GHC.Show.Show a) => GHC.Show.Show (Data.HFunctor.HFree t f a) instance forall k (t :: (k -> *) -> k -> *). Data.HFunctor.Internal.HFunctor t => Data.HFunctor.Internal.HFunctor (Data.HFunctor.HFree t) instance (Data.Functor.Classes.Show1 (t f), Data.Functor.Classes.Show1 f) => Data.Functor.Classes.Show1 (Data.HFunctor.HLift t f) instance (Data.Functor.Classes.Eq1 (t f), Data.Functor.Classes.Eq1 f) => Data.Functor.Classes.Eq1 (Data.HFunctor.HLift t f) instance (Data.Functor.Classes.Ord1 (t f), Data.Functor.Classes.Ord1 f) => Data.Functor.Classes.Ord1 (Data.HFunctor.HLift t f) instance forall k (t :: (k -> *) -> k -> *). Data.HFunctor.Internal.HFunctor t => Data.HFunctor.Internal.HFunctor (Data.HFunctor.HLift t) instance forall k e (f :: k). GHC.Classes.Ord e => Data.Functor.Classes.Ord1 (Data.HFunctor.ConstF e f) instance Data.HFunctor.Internal.HFunctor (Data.HFunctor.ConstF e) instance forall k e (f :: k). GHC.Classes.Eq e => Data.Functor.Classes.Eq1 (Data.HFunctor.ConstF e f) instance forall k e (f :: k). GHC.Read.Read e => Data.Functor.Classes.Read1 (Data.HFunctor.ConstF e f) instance forall k e (f :: k). GHC.Show.Show e => Data.Functor.Classes.Show1 (Data.HFunctor.ConstF e f) instance forall e k1 (f :: k1) k2 (a :: k2). (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable k1, Data.Typeable.Internal.Typeable k2, Data.Data.Data e) => Data.Data.Data (Data.HFunctor.ConstF e f a) instance forall e k1 (f :: k1) k2 (a :: k2). GHC.Generics.Generic (Data.HFunctor.ConstF e f a) instance forall e k (f :: k). Data.Traversable.Traversable (Data.HFunctor.ConstF e f) instance forall e k (f :: k). Data.Foldable.Foldable (Data.HFunctor.ConstF e f) instance forall e k (f :: k). GHC.Base.Functor (Data.HFunctor.ConstF e f) instance forall e k1 (f :: k1) k2 (a :: k2). GHC.Classes.Ord e => GHC.Classes.Ord (Data.HFunctor.ConstF e f a) instance forall e k1 (f :: k1) k2 (a :: k2). GHC.Classes.Eq e => GHC.Classes.Eq (Data.HFunctor.ConstF e f a) instance forall e k1 (f :: k1) k2 (a :: k2). GHC.Read.Read e => GHC.Read.Read (Data.HFunctor.ConstF e f a) instance forall e k1 (f :: k1) k2 (a :: k2). GHC.Show.Show e => GHC.Show.Show (Data.HFunctor.ConstF e f a) instance forall k (f :: k). Data.Functor.Classes.Ord1 (Data.HFunctor.ProxyF f) instance Data.HFunctor.Internal.HFunctor Data.HFunctor.ProxyF instance forall k (f :: k). Data.Functor.Classes.Eq1 (Data.HFunctor.ProxyF f) instance forall k (f :: k). Data.Functor.Classes.Read1 (Data.HFunctor.ProxyF f) instance forall k (f :: k). Data.Functor.Classes.Show1 (Data.HFunctor.ProxyF f) instance forall k1 (f :: k1) k2 (a :: k2). (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable k1, Data.Typeable.Internal.Typeable k2) => Data.Data.Data (Data.HFunctor.ProxyF f a) instance forall k1 (f :: k1) k2 (a :: k2). GHC.Generics.Generic (Data.HFunctor.ProxyF f a) instance forall k (f :: k). Data.Traversable.Traversable (Data.HFunctor.ProxyF f) instance forall k (f :: k). Data.Foldable.Foldable (Data.HFunctor.ProxyF f) instance forall k (f :: k). GHC.Base.Functor (Data.HFunctor.ProxyF f) instance forall k1 (f :: k1) k2 (a :: k2). GHC.Classes.Ord (Data.HFunctor.ProxyF f a) instance forall k1 (f :: k1) k2 (a :: k2). GHC.Classes.Eq (Data.HFunctor.ProxyF f a) instance forall k1 (f :: k1) k2 (a :: k2). GHC.Read.Read (Data.HFunctor.ProxyF f a) instance forall k1 (f :: k1) k2 (a :: k2). GHC.Show.Show (Data.HFunctor.ProxyF f a) -- | This module provides tools for working with unary functor combinators -- that represent interpretable schemas. -- -- These are types t that take a functor f and return a -- new functor t f, enhancing f with new structure and -- abilities. -- -- For these, we have: -- --
-- inject :: f a -> t f a ---- -- which lets you "lift" an f a into its transformed version, -- and also: -- --
-- interpret -- :: C t g -- => (forall x. f a -> g a) -- -> t f a -- -> g a ---- -- that lets you "interpret" a t f a into a context g -- a, essentially "running" the computaiton that it encodes. The -- context is required to have a typeclass constraints that reflects what -- is "required" to be able to run a functor combinator. -- -- Every single instance provides different tools. Check out the instance -- list for a nice list of useful combinators, or also the README for a -- high-level rundown. -- -- See Data.Functor.Tensor for binary functor combinators that mix -- together two or more different functors. module Data.HFunctor.Interpret -- | An Interpret lets us move in and out of the "enhanced" -- Functor. -- -- For example, Free f is f enhanced with -- monadic structure. We get: -- --
-- inject :: f a -> Free f a -- interpret :: Monad m => (forall x. f x -> m x) -> Free f a -> m a ---- -- inject will let us use our f inside the enhanced -- Free f. interpret will let us "extract" the -- f from a Free f if we can give an -- interpreting function that interprets f into some -- target Monad. -- -- The type family C tells us the typeclass constraint of the -- "target" functor. For Free, it is Monad, but for other -- Interpret instances, we might have other constraints. -- -- We enforce that: -- --
-- interpret id . inject == id -- -- or -- retract . inject == id ---- -- That is, if we lift a value into our structure, then immediately -- interpret it out as itself, it should lave the value unchanged. class Inject t => Interpret t where { -- | The constraint on the target context of interpret. It's -- basically the constraint that allows you to "exit" or "run" an -- Interpret. type family C t :: (Type -> Type) -> Constraint; } -- | Remove the f out of the enhanced t f structure, -- provided that f satisfies the necessary constraints. If it -- doesn't, it needs to be properly interpreted out. retract :: (Interpret t, C t f) => t f ~> f -- | Given an "interpeting function" from f to g, -- interpret the f out of the t f into a final context -- g. interpret :: (Interpret t, C t g) => (f ~> g) -> t f ~> g -- | A convenient flipped version of interpret. forI :: (Interpret t, C t g) => t f a -> (f ~> g) -> g a -- | Useful wrapper over interpret to allow you to directly extract -- a value b out of the t f a, if you can convert f -- x into b. -- -- Note that depending on the constraints on the interpretation of -- t, you may have extra constraints on b. -- --
-- -- get the length of the Map String in the Step. -- collectI length -- :: Step (Map String) Bool -- -> Int --getI :: (Interpret t, C t (Const b)) => (forall x. f x -> b) -> t f a -> b -- | Useful wrapper over getI to allow you to collect a b -- from all instances of f inside a t f a. -- -- This will work if C t is Unconstrained, -- Apply, or Applicative. -- --
-- -- get the lengths of all Map Strings in the Ap. -- collectI length -- :: Ap (Map String) Bool -- -> [Int] --collectI :: (Interpret t, C t (Const [b])) => (forall x. f x -> b) -> t f a -> [b] -- | A constraint on a for both c a and d a. -- Requiring AndC Show Eq a is the same as -- requiring (Show a, Eq a). class (c a, d a) => AndC c d a instance forall k (c :: k -> GHC.Types.Constraint) (a :: k) (d :: k -> GHC.Types.Constraint). (c a, d a) => Data.HFunctor.Interpret.AndC c d a instance (Data.HFunctor.Interpret.Interpret s, Data.HFunctor.Interpret.Interpret t) => Data.HFunctor.Interpret.Interpret (Control.Monad.Trans.Compose.ComposeT s t) instance Data.HFunctor.Interpret.Interpret Data.Functor.Coyoneda.Coyoneda instance Data.HFunctor.Interpret.Interpret Control.Applicative.Free.Ap instance Data.HFunctor.Interpret.Interpret Control.Applicative.ListF.ListF instance Data.HFunctor.Interpret.Interpret Control.Applicative.ListF.NonEmptyF instance Data.HFunctor.Interpret.Interpret Control.Applicative.ListF.MaybeF instance GHC.Base.Monoid k => Data.HFunctor.Interpret.Interpret (Control.Applicative.ListF.MapF k) instance GHC.Base.Monoid k => Data.HFunctor.Interpret.Interpret (Control.Applicative.ListF.NEMapF k) instance Data.HFunctor.Interpret.Interpret Control.Applicative.Step.Step instance Data.HFunctor.Interpret.Interpret Control.Applicative.Step.Steps instance Data.HFunctor.Interpret.Interpret Control.Applicative.Step.Flagged instance Data.HFunctor.Interpret.Interpret (Data.Functor.These.These1 f) instance Data.HFunctor.Interpret.Interpret Control.Alternative.Free.Alt instance Data.Functor.Plus.Plus f => Data.HFunctor.Interpret.Interpret ((GHC.Generics.:*:) f) instance Data.Functor.Plus.Plus f => Data.HFunctor.Interpret.Interpret (Data.Functor.Product.Product f) instance Data.HFunctor.Interpret.Interpret ((GHC.Generics.:+:) f) instance Data.HFunctor.Interpret.Interpret (Data.Functor.Sum.Sum f) instance Data.HFunctor.Interpret.Interpret (GHC.Generics.M1 i c) instance Data.HFunctor.Interpret.Interpret Control.Monad.Freer.Church.Free instance Data.HFunctor.Interpret.Interpret Control.Monad.Freer.Church.Free1 instance Data.HFunctor.Interpret.Interpret Control.Applicative.Free.Final.Ap instance Data.HFunctor.Interpret.Interpret Control.Applicative.Free.Fast.Ap instance Data.HFunctor.Interpret.Interpret Control.Monad.Trans.Identity.IdentityT instance Data.HFunctor.Interpret.Interpret Control.Applicative.Lift.Lift instance Data.HFunctor.Interpret.Interpret Data.Functor.Bind.Class.MaybeApply instance Data.HFunctor.Interpret.Interpret Control.Applicative.Backwards.Backwards instance Data.HFunctor.Interpret.Interpret Data.Functor.Bind.Class.WrappedApplicative instance Data.HFunctor.Interpret.Interpret (Control.Monad.Trans.Reader.ReaderT r) instance GHC.Base.Monoid e => Data.HFunctor.Interpret.Interpret (Control.Comonad.Trans.Env.EnvT e) instance Data.HFunctor.Interpret.Interpret Data.Functor.Reverse.Reverse instance Data.HFunctor.Interpret.Interpret Data.HFunctor.ProxyF instance GHC.Base.Monoid e => Data.HFunctor.Interpret.Interpret (Data.HFunctor.ConstF e) instance Data.HFunctor.Interpret.Interpret t => Data.HFunctor.Interpret.Interpret (Data.HFunctor.HLift t) instance Data.HFunctor.Interpret.Interpret t => Data.HFunctor.Interpret.Interpret (Data.HFunctor.HFree t) -- | This module provides an abstraction for "two-argument functor -- combinators", HBifunctor, as well as some useful combinators. module Data.HBifunctor -- | A HBifunctor is like an HFunctor, but it enhances -- two different functors instead of just one. -- -- Usually, it enhaces them "together" in some sort of combining way. -- -- This typeclass provides a uniform instance for "swapping out" or -- "hoisting" the enhanced functors. We can hoist the first one with -- hleft, the second one with hright, or both at the same -- time with hbimap. -- -- For example, the f :*: g type gives us "both f and -- g": -- --
-- data (f :*: g) a = f a :*: g a ---- -- It combines both f and g into a unified structure -- --- here, it does it by providing both f and g. -- -- The single law is: -- --
-- hbimap id id == id ---- -- This ensures that hleft, hright, and hbimap do -- not affect the structure that t adds on top of the underlying -- functors. class HBifunctor t -- | Swap out the first transformed functor. hleft :: HBifunctor t => (f ~> j) -> t f g ~> t j g -- | Swap out the second transformed functor. hright :: HBifunctor t => (g ~> k) -> t f g ~> t f k -- | Swap out both transformed functors at the same time. hbimap :: HBifunctor t => (f ~> j) -> (g ~> k) -> t f g ~> t j k -- | Useful newtype to allow us to derive an HFunctor instance from -- any instance of HBifunctor, using -XDerivingVia. -- -- For example, because we have instance HBifunctor -- Day, we can write: -- --
-- deriving via (WrappedHBifunctor Day f) instance HFunctor (Day f) ---- -- to give us an automatic HFunctor instance and save us some -- work. newtype WrappedHBifunctor t (f :: k -> Type) (g :: k -> Type) a WrapHBifunctor :: t f g a -> WrappedHBifunctor t a [unwrapHBifunctor] :: WrappedHBifunctor t a -> t f g a -- | Lift two isomorphisms on each side of a bifunctor to become an -- isomorphism between the two bifunctor applications. -- -- Basically, if f and f' are isomorphic, and -- g and g' are isomorphic, then t f g is -- isomorphic to t f' g'. overHBifunctor :: HBifunctor t => (f <~> f') -> (g <~> g') -> t f g <~> t f' g' -- | An HBifunctor that ignores its second input. Like a :+: -- with no R1/right branch. -- -- This is Joker from Data.Bifunctors.Joker, but given a -- more sensible name for its purpose. newtype LeftF f g a LeftF :: f a -> LeftF f g a [runLeftF] :: LeftF f g a -> f a -- | An HBifunctor that ignores its first input. Like a :+: -- with no L1/left branch. -- -- In its polykinded form (on f), it is essentially a -- higher-order version of Tagged. newtype RightF f g a RightF :: g a -> RightF f g a [runRightF] :: RightF f g a -> g a instance forall k (f :: k -> *). Data.HFunctor.Internal.HFunctor (Data.HBifunctor.RightF f) instance forall k (g :: * -> *) (f :: k). Data.Functor.Classes.Ord1 g => Data.Functor.Classes.Ord1 (Data.HBifunctor.RightF f g) instance Data.HFunctor.Internal.HBifunctor Data.HBifunctor.RightF instance forall k1 k2 (f :: k2). Data.HFunctor.Internal.HFunctor (Data.HBifunctor.RightF f) instance forall k1 k2 (f :: k2). Data.HFunctor.Inject (Data.HBifunctor.RightF f) instance forall k1 k2 (f :: k2). Data.HFunctor.HBind (Data.HBifunctor.RightF f) instance forall k (f :: k). Data.HFunctor.Interpret.Interpret (Data.HBifunctor.RightF f) instance forall k (g :: * -> *) (f :: k). Data.Functor.Classes.Eq1 g => Data.Functor.Classes.Eq1 (Data.HBifunctor.RightF f g) instance forall k (g :: * -> *) (f :: k). Data.Functor.Classes.Read1 g => Data.Functor.Classes.Read1 (Data.HBifunctor.RightF f g) instance forall k (g :: * -> *) (f :: k). Data.Functor.Classes.Show1 g => Data.Functor.Classes.Show1 (Data.HBifunctor.RightF f g) instance forall k1 (f :: k1) k2 (g :: k2 -> *) (a :: k2). (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable g, Data.Typeable.Internal.Typeable k1, Data.Typeable.Internal.Typeable k2, Data.Data.Data (g a)) => Data.Data.Data (Data.HBifunctor.RightF f g a) instance forall k1 (f :: k1) k2 (g :: k2 -> *) (a :: k2). GHC.Generics.Generic (Data.HBifunctor.RightF f g a) instance forall k (f :: k) (g :: * -> *). Data.Traversable.Traversable g => Data.Traversable.Traversable (Data.HBifunctor.RightF f g) instance forall k (f :: k) (g :: * -> *). Data.Foldable.Foldable g => Data.Foldable.Foldable (Data.HBifunctor.RightF f g) instance forall k (f :: k) (g :: * -> *). GHC.Base.Functor g => GHC.Base.Functor (Data.HBifunctor.RightF f g) instance forall k1 (f :: k1) k2 (g :: k2 -> *) (a :: k2). GHC.Classes.Ord (g a) => GHC.Classes.Ord (Data.HBifunctor.RightF f g a) instance forall k1 (f :: k1) k2 (g :: k2 -> *) (a :: k2). GHC.Classes.Eq (g a) => GHC.Classes.Eq (Data.HBifunctor.RightF f g a) instance forall k1 (f :: k1) k2 (g :: k2 -> *) (a :: k2). GHC.Read.Read (g a) => GHC.Read.Read (Data.HBifunctor.RightF f g a) instance forall k1 (f :: k1) k2 (g :: k2 -> *) (a :: k2). GHC.Show.Show (g a) => GHC.Show.Show (Data.HBifunctor.RightF f g a) instance forall k (f :: k -> *). Data.HFunctor.Internal.HFunctor (Data.HBifunctor.LeftF f) instance Data.Traversable.Traversable f => Data.Bitraversable.Bitraversable (Data.HBifunctor.LeftF f) instance GHC.Base.Applicative f => Data.Biapplicative.Biapplicative (Data.HBifunctor.LeftF f) instance Data.HFunctor.Internal.HBifunctor Data.HBifunctor.LeftF instance Data.Foldable.Foldable f => Data.Bifoldable.Bifoldable (Data.HBifunctor.LeftF f) instance GHC.Base.Functor f => Data.Bifunctor.Bifunctor (Data.HBifunctor.LeftF f) instance forall k (f :: * -> *) (g :: k). Data.Functor.Classes.Ord1 f => Data.Functor.Classes.Ord1 (Data.HBifunctor.LeftF f g) instance forall k (f :: * -> *) (g :: k). Data.Functor.Classes.Eq1 f => Data.Functor.Classes.Eq1 (Data.HBifunctor.LeftF f g) instance forall k (f :: * -> *) (g :: k). Data.Functor.Classes.Read1 f => Data.Functor.Classes.Read1 (Data.HBifunctor.LeftF f g) instance forall k (f :: * -> *) (g :: k). Data.Functor.Classes.Show1 f => Data.Functor.Classes.Show1 (Data.HBifunctor.LeftF f g) instance forall k1 (f :: k1 -> *) k2 (g :: k2) (a :: k1). (Data.Typeable.Internal.Typeable g, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable k2, Data.Typeable.Internal.Typeable k1, Data.Data.Data (f a)) => Data.Data.Data (Data.HBifunctor.LeftF f g a) instance forall k1 (f :: k1 -> *) k2 (g :: k2) (a :: k1). GHC.Generics.Generic (Data.HBifunctor.LeftF f g a) instance forall (f :: * -> *) k (g :: k). Data.Traversable.Traversable f => Data.Traversable.Traversable (Data.HBifunctor.LeftF f g) instance forall (f :: * -> *) k (g :: k). Data.Foldable.Foldable f => Data.Foldable.Foldable (Data.HBifunctor.LeftF f g) instance forall (f :: * -> *) k (g :: k). GHC.Base.Functor f => GHC.Base.Functor (Data.HBifunctor.LeftF f g) instance forall k1 (f :: k1 -> *) k2 (g :: k2) (a :: k1). GHC.Classes.Ord (f a) => GHC.Classes.Ord (Data.HBifunctor.LeftF f g a) instance forall k1 (f :: k1 -> *) k2 (g :: k2) (a :: k1). GHC.Classes.Eq (f a) => GHC.Classes.Eq (Data.HBifunctor.LeftF f g a) instance forall k1 (f :: k1 -> *) k2 (g :: k2) (a :: k1). GHC.Read.Read (f a) => GHC.Read.Read (Data.HBifunctor.LeftF f g a) instance forall k1 (f :: k1 -> *) k2 (g :: k2) (a :: k1). GHC.Show.Show (f a) => GHC.Show.Show (Data.HBifunctor.LeftF f g a) -- | The free Apply. Provides Ap1 and various utility -- methods. See Ap1 for more details. -- -- Ideally Ap1 would be in the free package. However, it is -- defined here for now. module Data.Functor.Apply.Free -- | One or more fs convolved with itself. -- -- Essentially: -- --
-- Ap1 f -- ~ f -- one f -- :+: (f `Day' f) -- two f's -- :+: (f `Day` f `Day` f) -- three f's -- :+: (f `Day` f `Day` f `Day` f) -- four f's -- :+: ... -- etc. ---- -- Useful if you want to promote an f to a situation with "at -- least one f sequenced with itself". -- -- Mostly useful for its HFunctor and Interpret instance, -- along with its relationship with Ap and Day. -- -- This is the free Apply --- Basically a "non-empty" Ap. -- -- The construction here is based on Ap, similar to now -- NonEmpty is built on list. data Ap1 :: (Type -> Type) -> Type -> Type [Ap1] :: f a -> Ap f (a -> b) -> Ap1 f b -- | An Ap1 is a "non-empty" Ap; this function "forgets" the -- non-empty property and turns it back into a normal Ap. toAp :: Ap1 f ~> Ap f -- | Convert an Ap into an Ap1 if possible. If the Ap -- was "empty", return the Pure value instead. fromAp :: Ap f ~> (Identity :+: Ap1 f) -- | Embed an f into Ap1. liftAp1 :: f ~> Ap1 f -- | Extract the f out of the Ap1. -- --
-- retractAp1 . liftAp1 == id --retractAp1 :: Apply f => Ap1 f ~> f -- | Interpret an Ap f into some Apply context -- g. runAp1 :: Apply g => (f ~> g) -> Ap1 f ~> g instance GHC.Base.Functor (Data.Functor.Apply.Free.Ap1 f) instance Data.Functor.Bind.Class.Apply (Data.Functor.Apply.Free.Ap1 f) instance Data.HFunctor.Internal.HFunctor Data.Functor.Apply.Free.Ap1 instance Data.HFunctor.Inject Data.Functor.Apply.Free.Ap1 instance Data.HFunctor.HBind Data.Functor.Apply.Free.Ap1 instance Data.HFunctor.Interpret.Interpret Data.Functor.Apply.Free.Ap1 -- | Provides Final, which can be considered the "free -- Interpret over a constraint": generate a handy Interpret -- instance for any constraint c. module Data.HFunctor.Final -- | A simple way to inject/reject into any eventual typeclass. -- -- In a way, this is the "ultimate" multi-purpose Interpret -- instance. You can use this to inject an f into a free -- structure of any typeclass. If you want f to have a -- Monad instance, for example, just use -- --
-- inject :: f a -> Final Monad f a ---- -- When you want to eventually interpret out the data, use: -- --
-- interpret :: (f ~> g) -> Final c f a -> g a ---- -- Essentially, Final c is the "free c". Final -- Monad is the free Monad, etc. -- -- Final can theoretically replace Ap, Ap1, -- ListF, NonEmptyF, MaybeF, Free, -- Identity, Coyoneda, and other instances of -- FreeOf, if you don't care about being able to pattern match on -- explicit structure. -- -- However, it cannot replace Interpret instances that are not -- free structures, like Step, Steps, Backwards, -- etc. -- -- Note that this doesn't have instances for all the typeclasses -- you could lift things into; you probably have to define your own if -- you want to use Final c as an instance of -- c (using liftFinal0, liftFinal1, -- liftFinal2 for help). newtype Final c f a Final :: (forall g. c g => (forall x. f x -> g x) -> g a) -> Final c f a [runFinal] :: Final c f a -> forall g. c g => (forall x. f x -> g x) -> g a -- | Concretize a Final. fromFinal :: (Interpret t, c (t f)) => Final c f ~> t f -- | Finalize an Interpret instance. -- --
-- toFinal :: Coyoneda f ~> Final Functor f -- toFinal :: Ap f ~> Final Applicative f -- toFinal :: Alt f ~> Final Alternative f -- toFinal :: Free f ~> Final Monad f -- toFinal :: Lift f ~> Final Pointed f -- toFinal :: ListF f ~> Final Plus f ---- -- Note that the instance of c for Final c must -- be defined. -- -- This operation can potentially forget structure in t. -- For example, we have: -- --
-- toFinal :: Steps f ~> Final Alt f ---- -- In this process, we lose the "positional" structure of Steps. -- -- In the case where toFinal doesn't lose any information, this -- will form an isomorphism with fromFinal, and t is -- known as the "Free c". For such a situation, t will -- have a FreeOf instance. toFinal :: (Interpret t, C t (Final c f)) => t f ~> Final c f -- | A typeclass associating a free structure with the typeclass it is free -- on. -- -- This essentially lists instances of Interpret where a "trip" -- through Final will leave it unchanged. -- --
-- fromFree . toFree == id -- toFree . fromFree == id ---- -- This can be useful because Final doesn't have a concrete -- structure that you can pattern match on and inspect, but t -- might. This lets you work on a concrete structure if you desire. class Interpret t => FreeOf c t | t -> c fromFree :: FreeOf c t => t f ~> Final c f toFree :: (FreeOf c t, Functor f) => Final c f ~> t f fromFree :: (FreeOf c t, C t (Final c f)) => t f ~> Final c f toFree :: (FreeOf c t, c (t f)) => Final c f ~> t f -- | The isomorphism between a free structure and its encoding as -- Final. finalizing :: (FreeOf c t, Functor f) => t f <~> Final c f -- | Re-interpret the context under a Final. hoistFinalC :: (forall g x. (c g => g x) -> d g => g x) -> Final c f a -> Final d f a -- | Lift an action into a Final. liftFinal0 :: (forall g. c g => g a) -> Final c f a -- | Map the action in a Final. liftFinal1 :: (forall g. c g => g a -> g b) -> Final c f a -> Final c f b -- | Merge two Final actions. liftFinal2 :: (forall g. c g => g a -> g b -> g d) -> Final c f a -> Final c f b -> Final c f d instance Data.HFunctor.Final.FreeOf GHC.Base.Functor Data.Functor.Coyoneda.Coyoneda instance Data.HFunctor.Final.FreeOf GHC.Base.Applicative Control.Applicative.Free.Ap instance Data.HFunctor.Final.FreeOf Data.Functor.Bind.Class.Apply Data.Functor.Apply.Free.Ap1 instance Data.HFunctor.Final.FreeOf GHC.Base.Applicative Control.Applicative.Free.Fast.Ap instance Data.HFunctor.Final.FreeOf GHC.Base.Alternative Control.Alternative.Free.Alt instance Data.HFunctor.Final.FreeOf GHC.Base.Monad Control.Monad.Freer.Church.Free instance Data.HFunctor.Final.FreeOf Data.Functor.Bind.Class.Bind Control.Monad.Freer.Church.Free1 instance Data.HFunctor.Final.FreeOf Data.Pointed.Pointed Control.Applicative.Lift.Lift instance Data.HFunctor.Final.FreeOf Data.Pointed.Pointed Data.Functor.Bind.Class.MaybeApply instance Data.HFunctor.Final.FreeOf Data.Functor.Alt.Alt Control.Applicative.ListF.NonEmptyF instance Data.HFunctor.Final.FreeOf Data.Functor.Plus.Plus Control.Applicative.ListF.ListF instance Data.HFunctor.Final.FreeOf Data.Constraint.Trivial.Unconstrained Control.Monad.Trans.Identity.IdentityT instance GHC.Base.Functor (Data.HFunctor.Final.Final GHC.Base.Functor f) instance GHC.Base.Functor (Data.HFunctor.Final.Final Data.Functor.Bind.Class.Apply f) instance Data.Functor.Bind.Class.Apply (Data.HFunctor.Final.Final Data.Functor.Bind.Class.Apply f) instance GHC.Base.Functor (Data.HFunctor.Final.Final Data.Functor.Bind.Class.Bind f) instance Data.Functor.Bind.Class.Apply (Data.HFunctor.Final.Final Data.Functor.Bind.Class.Bind f) instance Data.Functor.Bind.Class.Bind (Data.HFunctor.Final.Final Data.Functor.Bind.Class.Bind f) instance GHC.Base.Functor (Data.HFunctor.Final.Final GHC.Base.Applicative f) instance Data.Functor.Bind.Class.Apply (Data.HFunctor.Final.Final GHC.Base.Applicative f) instance GHC.Base.Applicative (Data.HFunctor.Final.Final GHC.Base.Applicative f) instance GHC.Base.Functor (Data.HFunctor.Final.Final GHC.Base.Alternative f) instance Data.Functor.Bind.Class.Apply (Data.HFunctor.Final.Final GHC.Base.Alternative f) instance GHC.Base.Applicative (Data.HFunctor.Final.Final GHC.Base.Alternative f) instance GHC.Base.Alternative (Data.HFunctor.Final.Final GHC.Base.Alternative f) instance GHC.Base.Functor (Data.HFunctor.Final.Final GHC.Base.Monad f) instance Data.Functor.Bind.Class.Apply (Data.HFunctor.Final.Final GHC.Base.Monad f) instance GHC.Base.Applicative (Data.HFunctor.Final.Final GHC.Base.Monad f) instance GHC.Base.Monad (Data.HFunctor.Final.Final GHC.Base.Monad f) instance GHC.Base.Functor (Data.HFunctor.Final.Final GHC.Base.MonadPlus f) instance GHC.Base.Applicative (Data.HFunctor.Final.Final GHC.Base.MonadPlus f) instance GHC.Base.Monad (Data.HFunctor.Final.Final GHC.Base.MonadPlus f) instance GHC.Base.Alternative (Data.HFunctor.Final.Final GHC.Base.MonadPlus f) instance GHC.Base.MonadPlus (Data.HFunctor.Final.Final GHC.Base.MonadPlus f) instance Data.Pointed.Pointed (Data.HFunctor.Final.Final Data.Pointed.Pointed f) instance GHC.Base.Functor (Data.HFunctor.Final.Final (Control.Monad.Reader.Class.MonadReader r) f) instance GHC.Base.Applicative (Data.HFunctor.Final.Final (Control.Monad.Reader.Class.MonadReader r) f) instance Data.Functor.Bind.Class.Apply (Data.HFunctor.Final.Final (Control.Monad.Reader.Class.MonadReader r) f) instance GHC.Base.Monad (Data.HFunctor.Final.Final (Control.Monad.Reader.Class.MonadReader r) f) instance Control.Monad.Reader.Class.MonadReader r (Data.HFunctor.Final.Final (Control.Monad.Reader.Class.MonadReader r) f) instance GHC.Base.Functor (Data.HFunctor.Final.Final Data.Functor.Alt.Alt f) instance Data.Functor.Alt.Alt (Data.HFunctor.Final.Final Data.Functor.Alt.Alt f) instance GHC.Base.Functor (Data.HFunctor.Final.Final Data.Functor.Plus.Plus f) instance Data.Functor.Alt.Alt (Data.HFunctor.Final.Final Data.Functor.Plus.Plus f) instance Data.Functor.Plus.Plus (Data.HFunctor.Final.Final Data.Functor.Plus.Plus f) instance Data.HFunctor.Internal.HFunctor (Data.HFunctor.Final.Final c) instance Data.HFunctor.Inject (Data.HFunctor.Final.Final c) instance Data.HFunctor.Interpret.Interpret (Data.HFunctor.Final.Final c) -- | This module provides tools for working with binary functor combinators -- that represent interpretable schemas. -- -- These are types HBifunctor t that take two functors -- f and g and returns a new functor t f g, -- that "mixes together" f and g in some way. -- -- The high-level usage of this is -- --
-- biretract :: t f f ~> f ---- -- which lets you fully "mix" together the two input functors. -- -- This class also associates each HBifunctor with its "semigroup -- functor combinator", so we can "squish together" repeated applications -- of t. -- -- That is, an SF t f a is either: -- --
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
-- data (f :*: g) a = f a :*: g a ---- -- We know that f :*: (g :*: h) is the same as (f :*: g) :*: -- h. class HBifunctor t => Associative t -- | The isomorphism between t f (t g h) a and t (t f g) h -- a. To use this isomorphism, see assoc and disassoc. associating :: (Associative t, Functor f, Functor g, Functor h) => t f (t g h) <~> t (t f g) h -- | Reassociate an application of t. assoc :: (Associative t, Functor f, Functor g, Functor h) => t f (t g h) ~> t (t f g) h -- | Reassociate an application of t. disassoc :: (Associative t, Functor f, Functor g, Functor h) => t (t f g) h ~> t f (t g h) -- | For some ts, you can represent the act of applying a functor -- f to t many times, as a single type. That is, there -- is some type SF t f that is equivalent to one of: -- --
-- biretract :: t f f ~> f -- binterpret :: (f ~> h) -> (g ~> h) -> t f g ~> h ---- -- which are like the HBifunctor versions of retract and -- interpret: they fully "mix" together the two inputs of -- t. -- -- Also useful is: -- --
-- toSF :: t f f a -> SF t f a ---- -- Which converts a t into its aggregate type SF. -- -- In reality, most Semigroupoidal instances are also -- Monoidal instances, so you can think of the separation as -- mostly to help organize functionality. However, there are two -- non-monoidal semigroupoidal instances of note: LeftF and -- RightF, which are higher order analogues of the First -- and Last semigroups, roughly. class (Associative t, Interpret (SF t)) => Semigroupoidal t where { -- | The "semigroup functor combinator" generated by t. -- -- A value of type SF t f a is equivalent to one of: -- --
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
t f (t f (t f (t f f))) a
-- x ~ NonEmptyF (x :| []) ~ inject x
-- x :*: y ~ NonEmptyF (x :| [y]) ~ toSF (x :*: y)
-- x :*: y :*: z ~ NonEmptyF (x :| [y,z])
-- -- etc.
--
--
-- You can create an "singleton" one with inject, or else one from
-- a single t f f with toSF.
type family SF t :: (Type -> Type) -> Type -> Type;
}
-- | If a SF t f represents multiple applications of t
-- f to itself, then we can also "append" two SF t
-- fs applied to themselves into one giant SF t f
-- containing all of the t fs.
appendSF :: Semigroupoidal t => t (SF t f) (SF t f) ~> SF t f
matchSF :: (Semigroupoidal t, Functor f) => SF t f ~> (f :+: t f (SF t f))
-- | Prepend an application of t f to the front of a SF
-- t f.
consSF :: Semigroupoidal t => t f (SF t f) ~> SF t f
-- | Embed a direct application of f to itself into a
-- SF t f.
toSF :: Semigroupoidal t => t f f ~> SF t f
-- | The HBifunctor analogy of retract. It retracts
-- both fs into a single f, effectively fully
-- mixing them together.
biretract :: (Semigroupoidal t, CS t f) => t f f ~> f
-- | The HBifunctor analogy of interpret. It takes two
-- interpreting functions, and mixes them together into a target functor
-- h.
binterpret :: (Semigroupoidal t, CS t h) => (f ~> h) -> (g ~> h) -> t f g ~> h
-- | Convenient alias for the constraint required for biretract,
-- binterpret, etc.
--
-- It's usually a constraint on the target/result context of
-- interpretation that allows you to "exit" or "run" a
-- Semigroupoidal t.
type CS t = C (SF t)
-- | An SF t f represents the successive application of
-- t to f, over and over again. So, that means that an
-- SF t f must either be a single f, or an t
-- f (SF t f).
--
-- matchingSF states that these two are isomorphic. Use
-- matchSF and inject !*! consSF to
-- convert between one and the other.
matchingSF :: (Semigroupoidal t, Functor f) => SF t f <~> (f :+: t f (SF t f))
-- | Useful wrapper over binterpret to allow you to directly extract
-- a value b out of the t f a, if you can convert f
-- x into b.
--
-- Note that depending on the constraints on the interpretation of
-- t, you may have extra constraints on b.
--
-- -- -- Return the length of either the list, or the Map, depending on which -- -- one s in the + -- biget length length -- :: ([] :+: Map Int) Char -- -> Int -- -- -- Return the length of both the list and the map, added together -- biget (Sum . length) (Sum . length) -- :: Day [] (Map Int) Char -- -> Sum Int --biget :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x -> b) -> (forall x. g x -> b) -> t f g a -> b -- | Useful wrapper over biget to allow you to collect a b -- from all instances of f and g inside a t f g -- a. -- -- This will work if C t is Unconstrained, -- Apply, or Applicative. bicollect :: (Semigroupoidal t, CS t (Const [b])) => (forall x. f x -> b) -> (forall x. g x -> b) -> t f g a -> [b] -- | Infix alias for binterpret (!*!) :: (Semigroupoidal t, CS t h) => (f ~> h) -> (g ~> h) -> t f g ~> h infixr 5 !*! -- | Infix alias for biget -- --
-- -- Return the length of either the list, or the Map, depending on which -- -- one s in the + -- length !$! length -- :: ([] :+: Map Int) Char -- -> Int -- -- -- Return the length of both the list and the map, added together -- Sum . length !$! Sum . length -- :: Day [] (Map Int) Char -- -> Sum Int --(!$!) :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x -> b) -> (forall x. g x -> b) -> t f g a -> b infixr 5 !$! instance Data.HBifunctor.Associative.Semigroupoidal (GHC.Generics.:*:) instance Data.HBifunctor.Associative.Semigroupoidal Data.Functor.Product.Product instance Data.HBifunctor.Associative.Semigroupoidal Data.Functor.Day.Day instance Data.HBifunctor.Associative.Semigroupoidal (GHC.Generics.:+:) instance Data.HBifunctor.Associative.Semigroupoidal Data.Functor.Sum.Sum instance Data.HBifunctor.Associative.Semigroupoidal Data.Functor.These.These1 instance Data.HBifunctor.Associative.Semigroupoidal Control.Monad.Freer.Church.Comp instance Data.HBifunctor.Associative.Semigroupoidal Data.Bifunctor.Joker.Joker instance Data.HBifunctor.Associative.Semigroupoidal Data.HBifunctor.LeftF instance Data.HBifunctor.Associative.Semigroupoidal Data.HBifunctor.RightF instance Data.HBifunctor.Associative.Associative (GHC.Generics.:*:) instance Data.HBifunctor.Associative.Associative Data.Functor.Product.Product instance Data.HBifunctor.Associative.Associative Data.Functor.Day.Day instance Data.HBifunctor.Associative.Associative (GHC.Generics.:+:) instance Data.HBifunctor.Associative.Associative Data.Functor.Sum.Sum instance Data.HBifunctor.Associative.Associative Data.Functor.These.These1 instance Data.HBifunctor.Associative.Associative Control.Applicative.Step.Void3 instance Data.HBifunctor.Associative.Associative Control.Monad.Freer.Church.Comp instance Data.HBifunctor.Associative.Associative Data.Bifunctor.Joker.Joker instance Data.HBifunctor.Associative.Associative Data.HBifunctor.LeftF instance Data.HBifunctor.Associative.Associative Data.HBifunctor.RightF -- | 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. -- -- The binary analog of Interpret is Monoidal (and -- Tensor). If your combinator is an instance of Monoidal, -- it means that you can "squish" both arguments together into an -- Interpret. For example: -- --
-- toMF :: (f :*: f) a -> ListF f a -- toMF :: Comp f f a -> Free f a -- toMF :: Day f f a -> Ap f a --module Data.HBifunctor.Tensor -- | An Associative HBifunctor can be a Tensor if -- there is some identity i where t i f is 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 with respect to this property. -- -- The Tensor is essentially the HBifunctor equivalent of -- Inject, with intro1 and intro2 taking the place -- of inject. class Associative t => Tensor t where { -- | The identity of Tensor t. If you "combine" f -- with the identity, it leaves f unchanged. -- -- For example, the identity of :*: is Proxy. This is -- because -- --
-- (Proxy :*: f) a
--
--
-- is equivalent to just
--
--
-- f a
--
--
-- :*:-ing f with Proxy gives you no additional
-- structure.
--
-- Another example:
--
--
-- (V1 :+: f) a
--
--
-- is equivalent to just
--
--
-- f a
--
--
-- because the L1 case is unconstructable.
type family I t :: Type -> Type;
}
-- | 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.
intro1 :: Tensor t => f ~> t f (I t)
-- | 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.
intro2 :: Tensor t => g ~> t (I t) g
-- | Witnesses the property that I t is the identity of
-- t: t f (I t) always leaves f unchanged, so
-- we can always just drop the I t.
elim1 :: (Tensor t, Functor f) => t f (I t) ~> f
-- | Witnesses the property that I t is the identity of
-- t: t (I t) g always leaves g unchanged, so
-- we can always just drop the I t.
elim2 :: (Tensor t, Functor g) => t (I t) g ~> g
-- | f is isomorphic to t f (I t): that is,
-- I t is the identity of t, and leaves
-- f unchanged.
rightIdentity :: (Tensor t, Functor f) => f <~> t f (I t)
-- | g is isomorphic to t (I t) g: that is,
-- I t is the identity of t, and leaves
-- g unchanged.
leftIdentity :: (Tensor t, Functor g) => g <~> t (I t) g
-- | leftIdentity (intro1 and elim1) for :+:
-- actually does not require Functor. This is the more general
-- version.
sumLeftIdentity :: f <~> (V1 :+: f)
-- | rightIdentity (intro2 and elim2) for :+:
-- actually does not require Functor. This is the more general
-- version.
sumRightIdentity :: f <~> (f :+: V1)
-- | leftIdentity (intro1 and elim1) for :*:
-- actually does not require Functor. This is the more general
-- version.
prodLeftIdentity :: f <~> (Proxy :*: f)
-- | rightIdentity (intro2 and elim2) for :*:
-- actually does not require Functor. This is the more general
-- version.
prodRightIdentity :: g <~> (g :*: Proxy)
-- | A Monoidal t is a Semigroupoidal, in that it
-- provides some type MF t f that is equivalent to one
-- of:
--
-- -- inL :: f a -> t f g a -- inR :: g a -> t f g a -- nilMF :: I a -> MF t f a ---- -- which are like the HBifunctor versions of inject: it -- lets you inject an f into t f g, so you can start -- doing useful mixing operations with it. nilMF lets you -- construct an "empty" MF t. -- -- Also useful is: -- --
-- toMF :: t f f a -> MF t f a ---- -- Which converts a t into its aggregate type MF class (Tensor t, Semigroupoidal t, Interpret (MF t)) => Monoidal t where { -- | The "monoidal functor combinator" induced by t. -- -- A value of type MF t f a is equivalent to one of: -- --
t f (t f (t f f)) a
t f (t f (t f (t f f))) a
-- Proxy ~ ListF [] ~ nilMF @(:*:)
-- x ~ ListF [x] ~ inject x
-- x :*: y ~ ListF [x,y] ~ toMF (x :*: y)
-- x :*: y :*: z ~ ListF [x,y,z]
-- -- etc.
--
--
-- You can create an "empty" one with nilMF, a "singleton" one
-- with inject, or else one from a single t f f with
-- toMF.
type family MF t :: (Type -> Type) -> Type -> Type;
}
-- | If a MF t f represents multiple applications of t
-- f to itself, then we can also "append" two MF t
-- fs applied to themselves into one giant MF t f
-- containing all of the t fs.
appendMF :: Monoidal t => t (MF t f) (MF t f) ~> MF t f
-- | Lets you convert an SF t f into a single application
-- of f to MF t f.
--
-- Analogous to a function NonEmpty a -> (a, [a])
--
-- Note that this is not reversible in general unless we have
-- Matchable t.
splitSF :: Monoidal t => SF t f ~> t f (MF t f)
-- | An MF t f is either empty, or a single application of
-- t to f and MF t f (the "head" and "tail").
-- This witnesses that isomorphism.
--
-- To use this property, see nilMF, consMF, and
-- unconsMF.
splittingMF :: Monoidal t => MF t f <~> (I t :+: t f (MF t f))
-- | Embed a direct application of f to itself into a
-- MF t f.
toMF :: Monoidal t => t f f ~> MF t f
-- | SF t f is "one or more fs", and 'MF 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:
--
-- -- fromSF @(:*:) :: NonEmptyF f a -> ListF f a -- fromSF @Comp :: Free1 f a -> Free f a --fromSF :: Monoidal t => SF t f ~> MF t f -- | If we have an I t, we can generate an f based -- on how it interacts with t. -- -- Specialized (and simplified), this type is: -- --
-- pureT @Day :: Applicative f => Identity a -> f a -- pure -- pureT @Comp :: Monad f => Identity a -> f a -- return -- pureT @(:*:) :: Plus f => Proxy a -> 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) pureT :: (Monoidal t, CM t f) => I t ~> f -- | If we have a constraint on the Monoidal satisfied, it should -- also imply the constraint on the Semigroupoidal. -- -- This is basically saying that C (SF t) should -- be a superclass of C (MF t). -- -- For example, for :*:, this type signature says that Alt -- is a superclass of Plus, so whenever you have Plus, you -- should always also have Alt. -- -- For Day, this type signature says that Apply is a -- superclass of Applicative, so whenever you have -- Applicative, you should always also have Apply. -- -- This is necessary because in the current class hierarchy, Apply -- isn't a true superclass of Applicative. upgradeC -- basically "imbues" f with an Apply instance based on -- its Applicative instance, so things can be easier to use. -- -- For example, let's say I have a type Parser that is an -- Applicative instance, but the source library does not define an -- Apply instance. I cannot use biretract or -- binterpret with it, even though I should be able to, because -- they require Apply. -- -- That is: -- --
-- biretract :: Day Parser Parser a -> Parser a ---- -- is a type error, because it requires Apply Parser. -- -- But, if we know that Parser has an Applicative -- instance, we can use: -- --
-- upgradeC @Day (Proxy @Parser) biretract -- :: Day Parser Parser a -> a ---- -- and this will now typecheck properly. -- -- Ideally, Parser would also have an Apply instance. But -- we cannot control this if an external library defines Parser. -- -- (Alternatively you can just use biretractT.) -- -- Note that you should only use this if f doesn't already have -- the SF constraint. If it does, this could lead to conflicting -- instances. Only use this with specific, concrete fs. -- Otherwise this is unsafe and can possibly break coherence guarantees. -- -- The proxy argument can be provided using something like -- Proxy @f, to specify which f you want to -- upgrade. upgradeC :: (Monoidal t, CM t f) => proxy f -> (CS t f => r) -> r -- | Convenient alias for the constraint required for inL, -- inR, pureT, etc. -- -- It's usually a constraint on the target/result context of -- interpretation that allows you to "exit" or "run" a -- Monoidal t. type CM t = C (MF t) -- | Create the "empty MF@. -- -- If MF t f represents multiple applications of t -- f with itself, then nilMF gives us "zero applications of -- f". -- -- Note that t cannot be inferred from the input or output type -- of nilMF, so this function must always be called with -- -XTypeApplications: -- --
-- nilMF @Day :: Identity ~> Ap f -- nilMF @Comp :: Identity ~> Free f -- nilMF @(:*:) :: Proxy ~> ListF f --nilMF :: forall t f. Monoidal t => I t ~> MF t f -- | Lets us "cons" an application of f to the front of an -- MF t f. consMF :: Monoidal t => t f (MF t f) ~> MF t f -- | "Pattern match" on an MF t -- -- An MF t f is either empty, or a single application of -- t to f and MF t f (the "head" and "tail") -- -- This is analogous to the function uncons :: [a] -> Maybe -- (a, [a]). unconsMF :: Monoidal t => MF t f ~> (I t :+: t f (MF t f)) -- | 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. inL :: forall t f g. (Monoidal t, CM t g) => f ~> t f g -- | 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. inR :: forall t f g. (Monoidal t, CM t f) => g ~> t f g -- | Convenient wrapper over elim1 that lets us drop one of the -- arguments of a Tensor for free, without requiring any extra -- constraints (like for binterpret). -- -- See prodOutL for a version that does not require -- Functor f, specifically for :*:. outL :: (Tensor t, I t ~ Proxy, Functor f) => t f g ~> f -- | Convenient wrapper over elim2 that lets us drop one of the -- arguments of a Tensor for free, without requiring any -- constraints (like for binterpret). -- -- See prodOutR for a version that does not require -- Functor g, specifically for :*:. outR :: (Tensor t, I t ~ Proxy, Functor g) => t f g ~> g -- | This is biretract, but taking a C (MF t) -- constraint instead of a C (SF t) constraint. -- For example, for Day, it takes an Applicative constraint -- instead of an Apply constraint. -- -- In an ideal world, this would be not necessary, and we can use -- biretract. However, sometimes C (MF t) -- is not an actual subclass of C (SF t) (like -- Apply and Applicative), even though it should -- technically always be so. -- -- Note that you should only use this if f doesn't already have -- the SF constraint (for example, for Day, if f -- already has an Apply instance). If it does, this could lead to -- conflicting instances. If f already has the SF -- instance, just use biretract directly. Only use this with -- specific, concrete fs. biretractT :: forall t f. (Monoidal t, CM t f) => t f f ~> f -- | This is binterpret, but taking a C (MF -- t) constraint instead of a C (SF t) -- constraint. For example, for Day, it takes an -- Applicative constraint instead of an Apply constraint. -- -- In an ideal world, this would be not necessary, and we can use -- biretract. However, sometimes C (MF t) -- is not an actual subclass of C (SF t) (like -- Apply and Applicative), even though it should -- technically always be so. -- -- Note that you should only use this if f doesn't already have -- the SF constraint (for example, for Day, if f -- already has an Apply instance). If it does, this could lead to -- conflicting instances. If f already has the SF -- instance, just use biretract directly. Only use this with -- specific, concrete fs. binterpretT :: forall t f g h. (Monoidal t, CM t h) => (f ~> h) -> (g ~> h) -> t f g ~> h -- | outL for :*: actually does not require Functor. -- This is the more general version. prodOutL :: (f :*: g) ~> f -- | outR for :*: actually does not require Functor. -- This is the more general version. prodOutR :: (f :*: g) ~> g -- | For some t, we have the ability to "statically analyze" the -- MF t and pattern match and manipulate the structure -- without ever interpreting or retracting. These are Matchable. class Monoidal t => Matchable t -- | The inverse of splitSF. A consing of f to -- MF t f is non-empty, so it can be represented as an -- SF t f. -- -- This is analogous to a function uncurry (:|) :: (a, -- [a]) -> NonEmpty a. unsplitSF :: Matchable t => t f (MF t f) ~> SF t f -- | "Pattern match" on an MF t f: it is either empty, or -- it is non-empty (and so can be an SF 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: -- --
-- matchMF @Day :: Ap f a -> (Identity :+: Ap1 f) a --matchMF :: Matchable t => MF t f ~> (I t :+: SF t f) -- | An SF t f is isomorphic to an f consed with -- an MF t f, like how a NonEmpty a is -- isomorphic to (a, [a]). splittingSF :: Matchable t => SF t f <~> t f (MF t f) -- | An MF t f is isomorphic to either the empty case -- (I t) or the non-empty case (SF t f), -- like how [a] is isomorphic to Maybe -- (NonEmpty a). matchingMF :: forall t f. Matchable t => MF t f <~> (I t :+: SF t f) instance Data.HBifunctor.Tensor.Matchable (GHC.Generics.:*:) instance Data.HBifunctor.Tensor.Matchable Data.Functor.Product.Product instance Data.HBifunctor.Tensor.Matchable Data.Functor.Day.Day instance Data.HBifunctor.Tensor.Matchable (GHC.Generics.:+:) instance Data.HBifunctor.Tensor.Matchable Data.Functor.Sum.Sum instance Data.HBifunctor.Tensor.Monoidal (GHC.Generics.:*:) instance Data.HBifunctor.Tensor.Monoidal Data.Functor.Product.Product instance Data.HBifunctor.Tensor.Monoidal Data.Functor.Day.Day instance Data.HBifunctor.Tensor.Monoidal (GHC.Generics.:+:) instance Data.HBifunctor.Tensor.Monoidal Data.Functor.Sum.Sum instance Data.HBifunctor.Tensor.Monoidal Data.Functor.These.These1 instance Data.HBifunctor.Tensor.Monoidal Control.Monad.Freer.Church.Comp instance Data.HBifunctor.Tensor.Tensor (GHC.Generics.:*:) instance Data.HBifunctor.Tensor.Tensor Data.Functor.Product.Product instance Data.HBifunctor.Tensor.Tensor Data.Functor.Day.Day instance Data.HBifunctor.Tensor.Tensor (GHC.Generics.:+:) instance Data.HBifunctor.Tensor.Tensor Data.Functor.Sum.Sum instance Data.HBifunctor.Tensor.Tensor Data.Functor.These.These1 instance Data.HBifunctor.Tensor.Tensor Control.Monad.Freer.Church.Comp -- | This module provides an Interpretable data type of "linked list -- of tensor applications". -- -- The type Chain t, for any Monoidal t, -- is meant to be the same as MF t (the monoidal functor -- combinator for t), and represents "zero or more" applications -- of f to t. -- -- The type Chain1 t, for any Semigroupoidal -- t, is meant to be the same as SF t (the -- semigroupoidal functor combinator for t) and represents "one -- or more" applications of f to t. -- -- The advantage of using Chain and Chain1 over MF -- or SF is that they provide a universal interface for pattern -- matching and constructing such values, which may simplify working with -- new such functor combinators you might encounter. module Data.HFunctor.Chain -- | A useful construction that works like a "linked list" of t f -- applied to itself multiple times. That is, it contains t f f, -- t f (t f f), t f (t f (t f f)), etc, with f -- occuring zero or more times. It is meant to be the same as -- MF t. -- -- If t is Monoidal, then it means we can "collapse" this -- linked list into some final type MF t -- (rerollMF), and also extract it back into a linked list -- (unrollMF). -- -- So, a value of type Chain t (I t) f a is one of -- either: -- --
I t a
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
-- unrollMF = unfoldChain unconsMF --unrollMF :: Monoidal t => MF t f ~> Chain t (I t) f -- | A type MF t is supposed to represent the successive -- application of ts to itself. rerollSF takes an -- explicit Chain of applications of t to itself and -- rolls it back up into an MF t. -- --
-- rerollMF = foldChain nilMF consMF ---- -- Because t cannot be inferred from the input or output, you -- should call this with -XTypeApplications: -- --
-- rerollMF @Comp -- :: Chain Comp Identity f a -> Free f a --rerollMF :: forall t f. Monoidal t => Chain t (I t) f ~> MF t f -- | A type MF t is supposed to represent the successive -- application of ts to itself. The type Chain t -- (I t) f is an actual concrete ADT that contains successive -- applications of t to itself, and you can pattern match on -- each layer. -- -- unrollingMF states that the two types are isormorphic. Use -- unrollMF and rerollMF to convert between the two. unrollingMF :: Monoidal t => MF t f <~> Chain t (I t) f -- | Chain is a monoid with respect to t: we can "combine" -- them in an associative way. The identity here is anything made with -- the Done constructor. appendChain :: forall t f. Monoidal t => t (Chain t (I t) f) (Chain t (I t) f) ~> Chain t (I t) f -- | A useful construction that works like a "non-empty linked list" of -- t f applied to itself multiple times. That is, it contains -- t f f, t f (t f f), t f (t f (t f f)), etc, -- with f occuring one or more times. It is meant to be -- the same as SF t. -- -- A Chain1 t f a is explicitly one of: -- --
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
-- unrollSF = unfoldChain1 matchSF --unrollSF :: (Semigroupoidal t, Functor f) => SF t f ~> Chain1 t f -- | A type SF t is supposed to represent the successive -- application of ts to itself. rerollSF takes an -- explicit Chain1 of applications of t to itself and -- rolls it back up into an SF t. -- --
-- rerollSF = foldChain1 inject consSF --rerollSF :: Semigroupoidal t => Chain1 t f ~> SF t f -- | Chain1 is a semigroup with respect to t: we can -- "combine" them in an associative way. appendChain1 :: forall t f. (Semigroupoidal t, Functor f) => t (Chain1 t f) (Chain1 t f) ~> Chain1 t f -- | A Chain1 is "one or more linked fs", and a -- Chain is "zero or more linked fs". So, we can convert -- from a Chain1 to a Chain that always has at least one -- f. -- -- The result of this function always is made with More at the top -- level. fromChain1 :: Tensor t => Chain1 t f ~> Chain t (I t) f -- | A Chain1 t f is like a non-empty linked list of -- fs, and a Chain t (I t) f is a -- possibly-empty linked list of fs. This witnesses the fact -- that the former is isomorphic to f consed to the latter. splittingChain1 :: forall t f. (Matchable t, Functor f) => Chain1 t f <~> t f (Chain t (I t) f) -- | The "forward" function representing splittingChain1. Provided -- here as a separate function because it does not require -- Functor f. splitChain1 :: forall t f. Matchable t => Chain1 t f ~> t f (Chain t (I t) f) -- | A Chain t (I t) f is a linked list of -- fs, and a Chain1 t f is a non-empty linked -- list of fs. This witnesses the fact that a Chain t -- (I t) f is either empty (I t) or non-empty -- (Chain1 t f). matchingChain :: forall t f. (Matchable t, Functor f) => Chain t (I t) f <~> (I t :+: Chain1 t f) -- | The "reverse" function representing matchingChain. Provided -- here as a separate function because it does not require -- Functor f. unmatchChain :: forall t f. Matchable t => (I t :+: Chain1 t f) ~> Chain t (I t) f instance forall k (t :: (k -> *) -> (k -> *) -> k -> *) (f :: k -> *) (a :: k). GHC.Generics.Generic (Data.HFunctor.Chain.Chain1 t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> (k -> *) -> k -> *). (GHC.Classes.Eq (f a), GHC.Classes.Eq (t f (Data.HFunctor.Chain.Chain1 t f) a)) => GHC.Classes.Eq (Data.HFunctor.Chain.Chain1 t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> (k -> *) -> k -> *). (GHC.Classes.Ord (f a), GHC.Classes.Ord (t f (Data.HFunctor.Chain.Chain1 t f) a)) => GHC.Classes.Ord (Data.HFunctor.Chain.Chain1 t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> (k -> *) -> k -> *). (GHC.Show.Show (f a), GHC.Show.Show (t f (Data.HFunctor.Chain.Chain1 t f) a)) => GHC.Show.Show (Data.HFunctor.Chain.Chain1 t f a) instance forall k (f :: k -> *) (a :: k) (t :: (k -> *) -> (k -> *) -> k -> *). (GHC.Read.Read (f a), GHC.Read.Read (t f (Data.HFunctor.Chain.Chain1 t f) a)) => GHC.Read.Read (Data.HFunctor.Chain.Chain1 t f a) instance (GHC.Base.Functor f, GHC.Base.Functor (t f (Data.HFunctor.Chain.Chain1 t f))) => GHC.Base.Functor (Data.HFunctor.Chain.Chain1 t f) instance (Data.Foldable.Foldable f, Data.Foldable.Foldable (t f (Data.HFunctor.Chain.Chain1 t f))) => Data.Foldable.Foldable (Data.HFunctor.Chain.Chain1 t f) instance (Data.Traversable.Traversable f, Data.Traversable.Traversable (t f (Data.HFunctor.Chain.Chain1 t f))) => Data.Traversable.Traversable (Data.HFunctor.Chain.Chain1 t f) instance forall k1 k2 (i :: k2 -> *) (a :: k2) (t :: k1 -> (k2 -> *) -> k2 -> *) (f :: k1). (GHC.Classes.Eq (i a), GHC.Classes.Eq (t f (Data.HFunctor.Chain.Chain t i f) a)) => GHC.Classes.Eq (Data.HFunctor.Chain.Chain t i f a) instance forall k1 k2 (i :: k2 -> *) (a :: k2) (t :: k1 -> (k2 -> *) -> k2 -> *) (f :: k1). (GHC.Classes.Ord (i a), GHC.Classes.Ord (t f (Data.HFunctor.Chain.Chain t i f) a)) => GHC.Classes.Ord (Data.HFunctor.Chain.Chain t i f a) instance forall k1 k2 (i :: k2 -> *) (a :: k2) (t :: k1 -> (k2 -> *) -> k2 -> *) (f :: k1). (GHC.Show.Show (i a), GHC.Show.Show (t f (Data.HFunctor.Chain.Chain t i f) a)) => GHC.Show.Show (Data.HFunctor.Chain.Chain t i f a) instance forall k1 k2 (i :: k2 -> *) (a :: k2) (t :: k1 -> (k2 -> *) -> k2 -> *) (f :: k1). (GHC.Read.Read (i a), GHC.Read.Read (t f (Data.HFunctor.Chain.Chain t i f) a)) => GHC.Read.Read (Data.HFunctor.Chain.Chain t i f a) instance forall k (i :: * -> *) (t :: k -> (* -> *) -> * -> *) (f :: k). (GHC.Base.Functor i, GHC.Base.Functor (t f (Data.HFunctor.Chain.Chain t i f))) => GHC.Base.Functor (Data.HFunctor.Chain.Chain t i f) instance forall k (i :: * -> *) (t :: k -> (* -> *) -> * -> *) (f :: k). (Data.Foldable.Foldable i, Data.Foldable.Foldable (t f (Data.HFunctor.Chain.Chain t i f))) => Data.Foldable.Foldable (Data.HFunctor.Chain.Chain t i f) instance forall k (i :: * -> *) (t :: k -> (* -> *) -> * -> *) (f :: k). (Data.Traversable.Traversable i, Data.Traversable.Traversable (t f (Data.HFunctor.Chain.Chain t i f))) => Data.Traversable.Traversable (Data.HFunctor.Chain.Chain t i f) instance forall k (i :: * -> *) (t :: k -> (* -> *) -> * -> *) (f :: k). (Data.Functor.Classes.Eq1 i, Data.Functor.Classes.Eq1 (t f (Data.HFunctor.Chain.Chain t i f))) => Data.Functor.Classes.Eq1 (Data.HFunctor.Chain.Chain t i f) instance forall k (i :: * -> *) (t :: k -> (* -> *) -> * -> *) (f :: k). (Data.Functor.Classes.Ord1 i, Data.Functor.Classes.Ord1 (t f (Data.HFunctor.Chain.Chain t i f))) => Data.Functor.Classes.Ord1 (Data.HFunctor.Chain.Chain t i f) instance forall k (t :: k -> (* -> *) -> * -> *) (f :: k) (i :: * -> *). (Data.Functor.Classes.Show1 (t f (Data.HFunctor.Chain.Chain t i f)), Data.Functor.Classes.Show1 i) => Data.Functor.Classes.Show1 (Data.HFunctor.Chain.Chain t i f) instance forall k (i :: * -> *) (t :: k -> (* -> *) -> * -> *) (f :: k). (GHC.Base.Functor i, Data.Functor.Classes.Read1 (t f (Data.HFunctor.Chain.Chain t i f)), Data.Functor.Classes.Read1 i) => Data.Functor.Classes.Read1 (Data.HFunctor.Chain.Chain t i f) instance forall k1 k2 (t :: (k1 -> *) -> (k2 -> *) -> k2 -> *) (i :: k2 -> *). Data.HFunctor.Internal.HBifunctor t => Data.HFunctor.Internal.HFunctor (Data.HFunctor.Chain.Chain t i) instance (Data.HBifunctor.Tensor.Tensor t, i Data.Type.Equality.~ Data.HBifunctor.Tensor.I t) => Data.HFunctor.Inject (Data.HFunctor.Chain.Chain t i) instance (Data.HBifunctor.Tensor.Monoidal t, i Data.Type.Equality.~ Data.HBifunctor.Tensor.I t) => Data.HFunctor.Interpret.Interpret (Data.HFunctor.Chain.Chain t i) instance (Data.Functor.Classes.Eq1 f, Data.Functor.Classes.Eq1 (t f (Data.HFunctor.Chain.Chain1 t f))) => Data.Functor.Classes.Eq1 (Data.HFunctor.Chain.Chain1 t f) instance (Data.Functor.Classes.Ord1 f, Data.Functor.Classes.Ord1 (t f (Data.HFunctor.Chain.Chain1 t f))) => Data.Functor.Classes.Ord1 (Data.HFunctor.Chain.Chain1 t f) instance (Data.Functor.Classes.Show1 (t f (Data.HFunctor.Chain.Chain1 t f)), Data.Functor.Classes.Show1 f) => Data.Functor.Classes.Show1 (Data.HFunctor.Chain.Chain1 t f) instance (GHC.Base.Functor f, Data.Functor.Classes.Read1 (t f (Data.HFunctor.Chain.Chain1 t f)), Data.Functor.Classes.Read1 f) => Data.Functor.Classes.Read1 (Data.HFunctor.Chain.Chain1 t f) instance forall k (t :: (k -> *) -> (k -> *) -> k -> *). Data.HFunctor.Internal.HBifunctor t => Data.HFunctor.Internal.HFunctor (Data.HFunctor.Chain.Chain1 t) instance forall k (t :: (k -> *) -> (k -> *) -> k -> *). Data.HFunctor.Internal.HBifunctor t => Data.HFunctor.Inject (Data.HFunctor.Chain.Chain1 t) instance (Data.HFunctor.Internal.HBifunctor t, Data.HBifunctor.Associative.Semigroupoidal t) => Data.HFunctor.Interpret.Interpret (Data.HFunctor.Chain.Chain1 t) -- | Functor combinators and tools (typeclasses and utiility functions) to -- manipulate them. This is the main "entrypoint" of the library. -- -- Classes include: -- --
-- viewF :: (f <~> g) -> f a -> g a -- reviewF :: (f <~> g) -> g a -> a a ---- -- Use viewF to extract the "f to g" function, -- and reviewF to extract the "g to f" function. -- Reviewing and viewing the same value (or vice versa) leaves the value -- unchanged. -- -- One nice thing is that we can compose isomorphisms using . from -- Prelude: -- --
-- (.) :: f <~> g -- -> g <~> h -- -> f <~> h ---- -- Another nice thing about this representation is that we have the -- "identity" isomorphism by using id from Prelude. -- --
-- id :: f <~> g ---- -- As a convention, most isomorphisms have form "X-ing", where the -- forwards function is "ing". For example, we have: -- --
-- splittingSF :: Monoidal t => SF t a <~> t f (MF t f) -- splitSF :: Monoidal t => SF t a ~> t f (MF t f) --type f <~> g = forall p a. Profunctor p => p (g a) (g a) -> p (f a) (f a) infixr 0 <~> -- | An HFunctor can be thought of a unary "functor transformer" --- -- a basic functor combinator. It takes a functor as input and returns a -- functor as output. -- -- It "enhances" a functor with extra structure (sort of like how a monad -- transformer enhances a Monad with extra structure). -- -- As a uniform inteface, we can "swap the underlying functor" (also -- sometimes called "hoisting"). This is what hmap does: it lets -- us swap out the f in a t f for a t g. -- -- For example, the free monad Free takes a Functor and -- returns a new Functor. In the process, it provides a monadic -- structure over f. hmap lets us turn a Free -- f into a Free g: a monad built over f -- can be turned into a monad built over g. -- -- For the ability to move in and out of the enhanced functor, see -- Inject and Interpret. -- -- This class is similar to MFunctor from -- Control.Monad.Morph, but instances must work without a -- Monad constraint. class HFunctor t -- | If we can turn an f into a g, then we can turn a -- t f into a t g. -- -- It must be the case that -- --
-- hmap id == id ---- -- Essentially, t f adds some "extra structure" to f. -- hmap must swap out the functor, without affecting the added -- structure. -- -- For example, ListF f a is essentially a list of f -- as. If we hmap to swap out the f as for g -- as, then we must ensure that the "added structure" (here, the -- number of items in the list, and the ordering of those items) remains -- the same. So, hmap must preserve the number of items in the -- list, and must maintain the ordering. -- -- The law hmap id == id is a way of formalizing -- this property. hmap :: HFunctor t => (f ~> g) -> t f ~> t g -- | A typeclass for HFunctors where you can "inject" an f -- a into a t f a: -- --
-- inject :: f a -> t f a ---- -- If you think of t f a as an "enhanced f", then -- inject allows you to use an f as its enhanced form. -- -- With the exception of directly pattern matching on the result, -- inject itself is not too useful in the general case without -- Interpret to allow us to interpret or retrieve back the -- f. class HFunctor t => Inject t -- | Lift from f into the enhanced t f structure. -- Analogous to lift from MonadTrans. -- -- Note that this lets us "lift" a f a; if you want to lift an -- a with a -> t f a, check if t f is an -- instance of Applicative or Pointed. inject :: Inject t => f ~> t f -- | An Interpret lets us move in and out of the "enhanced" -- Functor. -- -- For example, Free f is f enhanced with -- monadic structure. We get: -- --
-- inject :: f a -> Free f a -- interpret :: Monad m => (forall x. f x -> m x) -> Free f a -> m a ---- -- inject will let us use our f inside the enhanced -- Free f. interpret will let us "extract" the -- f from a Free f if we can give an -- interpreting function that interprets f into some -- target Monad. -- -- The type family C tells us the typeclass constraint of the -- "target" functor. For Free, it is Monad, but for other -- Interpret instances, we might have other constraints. -- -- We enforce that: -- --
-- interpret id . inject == id -- -- or -- retract . inject == id ---- -- That is, if we lift a value into our structure, then immediately -- interpret it out as itself, it should lave the value unchanged. class Inject t => Interpret t where { -- | The constraint on the target context of interpret. It's -- basically the constraint that allows you to "exit" or "run" an -- Interpret. type family C t :: (Type -> Type) -> Constraint; } -- | Remove the f out of the enhanced t f structure, -- provided that f satisfies the necessary constraints. If it -- doesn't, it needs to be properly interpreted out. retract :: (Interpret t, C t f) => t f ~> f -- | Given an "interpeting function" from f to g, -- interpret the f out of the t f into a final context -- g. interpret :: (Interpret t, C t g) => (f ~> g) -> t f ~> g -- | A convenient flipped version of interpret. forI :: (Interpret t, C t g) => t f a -> (f ~> g) -> g a -- | Useful wrapper over interpret to allow you to directly extract -- a value b out of the t f a, if you can convert f -- x into b. -- -- Note that depending on the constraints on the interpretation of -- t, you may have extra constraints on b. -- --
-- -- get the length of the Map String in the Step. -- collectI length -- :: Step (Map String) Bool -- -> Int --getI :: (Interpret t, C t (Const b)) => (forall x. f x -> b) -> t f a -> b -- | Useful wrapper over getI to allow you to collect a b -- from all instances of f inside a t f a. -- -- This will work if C t is Unconstrained, -- Apply, or Applicative. -- --
-- -- get the lengths of all Map Strings in the Ap. -- collectI length -- :: Ap (Map String) Bool -- -> [Int] --collectI :: (Interpret t, C t (Const [b])) => (forall x. f x -> b) -> t f a -> [b] -- | A HBifunctor is like an HFunctor, but it enhances -- two different functors instead of just one. -- -- Usually, it enhaces them "together" in some sort of combining way. -- -- This typeclass provides a uniform instance for "swapping out" or -- "hoisting" the enhanced functors. We can hoist the first one with -- hleft, the second one with hright, or both at the same -- time with hbimap. -- -- For example, the f :*: g type gives us "both f and -- g": -- --
-- data (f :*: g) a = f a :*: g a ---- -- It combines both f and g into a unified structure -- --- here, it does it by providing both f and g. -- -- The single law is: -- --
-- hbimap id id == id ---- -- This ensures that hleft, hright, and hbimap do -- not affect the structure that t adds on top of the underlying -- functors. class HBifunctor t -- | Swap out the first transformed functor. hleft :: HBifunctor t => (f ~> j) -> t f g ~> t j g -- | Swap out the second transformed functor. hright :: HBifunctor t => (g ~> k) -> t f g ~> t f k -- | Swap out both transformed functors at the same time. hbimap :: HBifunctor t => (f ~> j) -> (g ~> k) -> t f g ~> t j k -- | An HBifunctor where it doesn't matter which binds first is -- Associative. Knowing this gives us a lot of power to rearrange -- the internals of our HFunctor at will. -- -- For example, for the functor product: -- --
-- data (f :*: g) a = f a :*: g a ---- -- We know that f :*: (g :*: h) is the same as (f :*: g) :*: -- h. class HBifunctor t => Associative t -- | The isomorphism between t f (t g h) a and t (t f g) h -- a. To use this isomorphism, see assoc and disassoc. associating :: (Associative t, Functor f, Functor g, Functor h) => t f (t g h) <~> t (t f g) h -- | For some ts, you can represent the act of applying a functor -- f to t many times, as a single type. That is, there -- is some type SF t f that is equivalent to one of: -- --
-- biretract :: t f f ~> f -- binterpret :: (f ~> h) -> (g ~> h) -> t f g ~> h ---- -- which are like the HBifunctor versions of retract and -- interpret: they fully "mix" together the two inputs of -- t. -- -- Also useful is: -- --
-- toSF :: t f f a -> SF t f a ---- -- Which converts a t into its aggregate type SF. -- -- In reality, most Semigroupoidal instances are also -- Monoidal instances, so you can think of the separation as -- mostly to help organize functionality. However, there are two -- non-monoidal semigroupoidal instances of note: LeftF and -- RightF, which are higher order analogues of the First -- and Last semigroups, roughly. class (Associative t, Interpret (SF t)) => Semigroupoidal t where { -- | The "semigroup functor combinator" generated by t. -- -- A value of type SF t f a is equivalent to one of: -- --
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
t f (t f (t f (t f f))) a
-- x ~ NonEmptyF (x :| []) ~ inject x
-- x :*: y ~ NonEmptyF (x :| [y]) ~ toSF (x :*: y)
-- x :*: y :*: z ~ NonEmptyF (x :| [y,z])
-- -- etc.
--
--
-- You can create an "singleton" one with inject, or else one from
-- a single t f f with toSF.
type family SF t :: (Type -> Type) -> Type -> Type;
}
-- | If a SF t f represents multiple applications of t
-- f to itself, then we can also "append" two SF t
-- fs applied to themselves into one giant SF t f
-- containing all of the t fs.
appendSF :: Semigroupoidal t => t (SF t f) (SF t f) ~> SF t f
-- | Prepend an application of t f to the front of a SF
-- t f.
consSF :: Semigroupoidal t => t f (SF t f) ~> SF t f
-- | Embed a direct application of f to itself into a
-- SF t f.
toSF :: Semigroupoidal t => t f f ~> SF t f
-- | The HBifunctor analogy of retract. It retracts
-- both fs into a single f, effectively fully
-- mixing them together.
biretract :: (Semigroupoidal t, CS t f) => t f f ~> f
-- | The HBifunctor analogy of interpret. It takes two
-- interpreting functions, and mixes them together into a target functor
-- h.
binterpret :: (Semigroupoidal t, CS t h) => (f ~> h) -> (g ~> h) -> t f g ~> h
-- | Convenient alias for the constraint required for biretract,
-- binterpret, etc.
--
-- It's usually a constraint on the target/result context of
-- interpretation that allows you to "exit" or "run" a
-- Semigroupoidal t.
type CS t = C (SF t)
-- | Useful wrapper over binterpret to allow you to directly extract
-- a value b out of the t f a, if you can convert f
-- x into b.
--
-- Note that depending on the constraints on the interpretation of
-- t, you may have extra constraints on b.
--
-- -- -- Return the length of either the list, or the Map, depending on which -- -- one s in the + -- biget length length -- :: ([] :+: Map Int) Char -- -> Int -- -- -- Return the length of both the list and the map, added together -- biget (Sum . length) (Sum . length) -- :: Day [] (Map Int) Char -- -> Sum Int --biget :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x -> b) -> (forall x. g x -> b) -> t f g a -> b -- | Useful wrapper over biget to allow you to collect a b -- from all instances of f and g inside a t f g -- a. -- -- This will work if C t is Unconstrained, -- Apply, or Applicative. bicollect :: (Semigroupoidal t, CS t (Const [b])) => (forall x. f x -> b) -> (forall x. g x -> b) -> t f g a -> [b] -- | Infix alias for binterpret (!*!) :: (Semigroupoidal t, CS t h) => (f ~> h) -> (g ~> h) -> t f g ~> h infixr 5 !*! -- | Infix alias for biget -- --
-- -- Return the length of either the list, or the Map, depending on which -- -- one s in the + -- length !$! length -- :: ([] :+: Map Int) Char -- -> Int -- -- -- Return the length of both the list and the map, added together -- Sum . length !$! Sum . length -- :: Day [] (Map Int) Char -- -> Sum Int --(!$!) :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x -> b) -> (forall x. g x -> b) -> t f g a -> b infixr 5 !$! -- | An Associative HBifunctor can be a Tensor if -- there is some identity i where t i f is 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 with respect to this property. -- -- The Tensor is essentially the HBifunctor equivalent of -- Inject, with intro1 and intro2 taking the place -- of inject. class Associative t => Tensor t where { -- | The identity of Tensor t. If you "combine" f -- with the identity, it leaves f unchanged. -- -- For example, the identity of :*: is Proxy. This is -- because -- --
-- (Proxy :*: f) a
--
--
-- is equivalent to just
--
--
-- f a
--
--
-- :*:-ing f with Proxy gives you no additional
-- structure.
--
-- Another example:
--
--
-- (V1 :+: f) a
--
--
-- is equivalent to just
--
--
-- f a
--
--
-- because the L1 case is unconstructable.
type family I t :: Type -> Type;
}
-- | 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.
intro1 :: Tensor t => f ~> t f (I t)
-- | 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.
intro2 :: Tensor t => g ~> t (I t) g
-- | Witnesses the property that I t is the identity of
-- t: t f (I t) always leaves f unchanged, so
-- we can always just drop the I t.
elim1 :: (Tensor t, Functor f) => t f (I t) ~> f
-- | Witnesses the property that I t is the identity of
-- t: t (I t) g always leaves g unchanged, so
-- we can always just drop the I t.
elim2 :: (Tensor t, Functor g) => t (I t) g ~> g
-- | A Monoidal t is a Semigroupoidal, in that it
-- provides some type MF t f that is equivalent to one
-- of:
--
-- -- inL :: f a -> t f g a -- inR :: g a -> t f g a -- nilMF :: I a -> MF t f a ---- -- which are like the HBifunctor versions of inject: it -- lets you inject an f into t f g, so you can start -- doing useful mixing operations with it. nilMF lets you -- construct an "empty" MF t. -- -- Also useful is: -- --
-- toMF :: t f f a -> MF t f a ---- -- Which converts a t into its aggregate type MF class (Tensor t, Semigroupoidal t, Interpret (MF t)) => Monoidal t where { -- | The "monoidal functor combinator" induced by t. -- -- A value of type MF t f a is equivalent to one of: -- --
t f (t f (t f f)) a
t f (t f (t f (t f f))) a
-- Proxy ~ ListF [] ~ nilMF @(:*:)
-- x ~ ListF [x] ~ inject x
-- x :*: y ~ ListF [x,y] ~ toMF (x :*: y)
-- x :*: y :*: z ~ ListF [x,y,z]
-- -- etc.
--
--
-- You can create an "empty" one with nilMF, a "singleton" one
-- with inject, or else one from a single t f f with
-- toMF.
type family MF t :: (Type -> Type) -> Type -> Type;
}
-- | If a MF t f represents multiple applications of t
-- f to itself, then we can also "append" two MF t
-- fs applied to themselves into one giant MF t f
-- containing all of the t fs.
appendMF :: Monoidal t => t (MF t f) (MF t f) ~> MF t f
-- | Lets you convert an SF t f into a single application
-- of f to MF t f.
--
-- Analogous to a function NonEmpty a -> (a, [a])
--
-- Note that this is not reversible in general unless we have
-- Matchable t.
splitSF :: Monoidal t => SF t f ~> t f (MF t f)
-- | Embed a direct application of f to itself into a
-- MF t f.
toMF :: Monoidal t => t f f ~> MF t f
-- | SF t f is "one or more fs", and 'MF 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:
--
-- -- fromSF @(:*:) :: NonEmptyF f a -> ListF f a -- fromSF @Comp :: Free1 f a -> Free f a --fromSF :: Monoidal t => SF t f ~> MF t f -- | If we have an I t, we can generate an f based -- on how it interacts with t. -- -- Specialized (and simplified), this type is: -- --
-- pureT @Day :: Applicative f => Identity a -> f a -- pure -- pureT @Comp :: Monad f => Identity a -> f a -- return -- pureT @(:*:) :: Plus f => Proxy a -> 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) pureT :: (Monoidal t, CM t f) => I t ~> f -- | If we have a constraint on the Monoidal satisfied, it should -- also imply the constraint on the Semigroupoidal. -- -- This is basically saying that C (SF t) should -- be a superclass of C (MF t). -- -- For example, for :*:, this type signature says that Alt -- is a superclass of Plus, so whenever you have Plus, you -- should always also have Alt. -- -- For Day, this type signature says that Apply is a -- superclass of Applicative, so whenever you have -- Applicative, you should always also have Apply. -- -- This is necessary because in the current class hierarchy, Apply -- isn't a true superclass of Applicative. upgradeC -- basically "imbues" f with an Apply instance based on -- its Applicative instance, so things can be easier to use. -- -- For example, let's say I have a type Parser that is an -- Applicative instance, but the source library does not define an -- Apply instance. I cannot use biretract or -- binterpret with it, even though I should be able to, because -- they require Apply. -- -- That is: -- --
-- biretract :: Day Parser Parser a -> Parser a ---- -- is a type error, because it requires Apply Parser. -- -- But, if we know that Parser has an Applicative -- instance, we can use: -- --
-- upgradeC @Day (Proxy @Parser) biretract -- :: Day Parser Parser a -> a ---- -- and this will now typecheck properly. -- -- Ideally, Parser would also have an Apply instance. But -- we cannot control this if an external library defines Parser. -- -- (Alternatively you can just use biretractT.) -- -- Note that you should only use this if f doesn't already have -- the SF constraint. If it does, this could lead to conflicting -- instances. Only use this with specific, concrete fs. -- Otherwise this is unsafe and can possibly break coherence guarantees. -- -- The proxy argument can be provided using something like -- Proxy @f, to specify which f you want to -- upgrade. upgradeC :: (Monoidal t, CM t f) => proxy f -> (CS t f => r) -> r -- | Convenient alias for the constraint required for inL, -- inR, pureT, etc. -- -- It's usually a constraint on the target/result context of -- interpretation that allows you to "exit" or "run" a -- Monoidal t. type CM t = C (MF t) -- | Create the "empty MF@. -- -- If MF t f represents multiple applications of t -- f with itself, then nilMF gives us "zero applications of -- f". -- -- Note that t cannot be inferred from the input or output type -- of nilMF, so this function must always be called with -- -XTypeApplications: -- --
-- nilMF @Day :: Identity ~> Ap f -- nilMF @Comp :: Identity ~> Free f -- nilMF @(:*:) :: Proxy ~> ListF f --nilMF :: forall t f. Monoidal t => I t ~> MF t f -- | Lets us "cons" an application of f to the front of an -- MF t f. consMF :: Monoidal t => t f (MF t f) ~> MF t f -- | 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. inL :: forall t f g. (Monoidal t, CM t g) => f ~> t f g -- | 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. inR :: forall t f g. (Monoidal t, CM t f) => g ~> t f g -- | Convenient wrapper over elim1 that lets us drop one of the -- arguments of a Tensor for free, without requiring any extra -- constraints (like for binterpret). -- -- See prodOutL for a version that does not require -- Functor f, specifically for :*:. outL :: (Tensor t, I t ~ Proxy, Functor f) => t f g ~> f -- | Convenient wrapper over elim2 that lets us drop one of the -- arguments of a Tensor for free, without requiring any -- constraints (like for binterpret). -- -- See prodOutR for a version that does not require -- Functor g, specifically for :*:. outR :: (Tensor t, I t ~ Proxy, Functor g) => t f g ~> g -- | A covariant Functor suitable for Yoneda reduction data Coyoneda (f :: Type -> Type) a [Coyoneda] :: forall (f :: Type -> Type) a b. () => (b -> a) -> f b -> Coyoneda f a -- | A list of f as. Can be used to describe a product of many -- different values of type f a. -- -- This is the Free Plus. newtype ListF f a ListF :: [f a] -> ListF f a [runListF] :: ListF f a -> [f a] -- | A non-empty list of f as. Can be used to describe a product -- between many different possible values of type f a. -- -- Essentially: -- --
-- NonEmptyF f -- ~ f -- one f -- :+: (f :*: f) -- two f's -- :+: (f :*: f :*: f) -- three f's -- :+: (f :*: f :*: f :*: f) -- four f's -- :+: ... -- etc. ---- -- This is the Free Plus. newtype NonEmptyF f a NonEmptyF :: NonEmpty (f a) -> NonEmptyF f a [runNonEmptyF] :: NonEmptyF f a -> NonEmpty (f a) -- | A maybe f a. -- -- Can be useful for describing a "an f a that may or may not be -- there". -- -- This is the free structure for a "fail"-like typeclass that would only -- have zero :: f a. newtype MaybeF f a MaybeF :: Maybe (f a) -> MaybeF f a [runMaybeF] :: MaybeF f a -> Maybe (f a) -- | A map of f as, indexed by keys of type k. It can be -- useful for represeting a product of many different values of type -- f a, each "at" a different k location. -- -- Can be considered a combination of EnvT and ListF, in a -- way --- a MapF k f a is like a ListF -- (EnvT k f) a with unique (and ordered) keys. -- -- One use case might be to extend a schema with many "options", indexed -- by some string. -- -- For example, if you had a command line argument parser for a single -- command -- --
-- data Command a ---- -- Then you can represent a command line argument parser for -- multiple named commands with -- --
-- type Commands = MapF String Command ---- -- See NEMapF for a non-empty variant, if you want to enforce that -- your bag has at least one f a. newtype MapF k f a MapF :: Map k (f a) -> MapF k f a [runMapF] :: MapF k f a -> Map k (f a) -- | A non-empty map of f as, indexed by keys of type k. -- It can be useful for represeting a product of many different values of -- type f a, each "at" a different k location, where -- you need to have at least one f a at all times. -- -- Can be considered a combination of EnvT and NonEmptyF, -- in a way --- an NEMapF k f a is like a -- NonEmptyF (EnvT k f) a with unique (and -- ordered) keys. -- -- See MapF for some use cases. newtype NEMapF k f a NEMapF :: NEMap k (f a) -> NEMapF k f a [runNEMapF] :: NEMapF k f a -> NEMap k (f a) -- | The free Applicative for a Functor f. data Ap (f :: Type -> Type) a -- | One or more fs convolved with itself. -- -- Essentially: -- --
-- Ap1 f -- ~ f -- one f -- :+: (f `Day' f) -- two f's -- :+: (f `Day` f `Day` f) -- three f's -- :+: (f `Day` f `Day` f `Day` f) -- four f's -- :+: ... -- etc. ---- -- Useful if you want to promote an f to a situation with "at -- least one f sequenced with itself". -- -- Mostly useful for its HFunctor and Interpret instance, -- along with its relationship with Ap and Day. -- -- This is the free Apply --- Basically a "non-empty" Ap. -- -- The construction here is based on Ap, similar to now -- NonEmpty is built on list. data Ap1 :: (Type -> Type) -> Type -> Type [Ap1] :: f a -> Ap f (a -> b) -> Ap1 f b data Alt (f :: Type -> Type) a -- | A Free f is f enhanced with "sequential -- binding" capabilities. It allows you to sequence multiple fs -- one after the other, and also to determine "what f to -- sequence" based on the result of the computation so far. -- -- Essentially, you can think of this as "giving f a -- Monad instance", with all that that entails (return, -- >>=, etc.). -- -- Lift f into it with inject :: f a -> Free f -- a. When you finally want to "use" it, you can interpret it into -- any monadic context: -- --
-- interpret -- :: Monad g -- => (forall x. f x -> g x) -- -> Free f a -- -> g a ---- -- Structurally, this is equivalent to many "nested" f's. A value of type -- Free f a is either: -- --
a
f a
f (f a)
f (f (f a))
-- Step f a ~ (Natural, f a) -- Step f ~ ((,) Natural) :.: f -- functor composition ---- -- It is the fixed point of infinite applications of :+: (functor -- sums). -- -- Intuitively, in an infinite f :+: f :+: f :+: f ..., you have -- exactly one f somewhere. A Step f a -- has that f, with a Natural giving you "where" the -- f is in the long chain. -- -- Can be useful for using with the Monoidal instance of -- :+:. -- -- interpreting it requires no constraint on the target context. -- -- Note that this type and its instances equivalent to EnvT -- (Sum Natural). data Step f a Step :: Natural -> f a -> Step f a [stepPos] :: Step f a -> Natural [stepVal] :: Step f a -> f a -- | A non-empty map of Natural to f a. Basically, contains -- multiple f as, each at a given Natural index. -- --
-- Steps f a ~ Map Natural (f a) -- Steps f ~ Map Natural :.: f -- functor composition ---- -- It is the fixed point of applications of TheseT. -- -- You can think of this as an infinite sparse array of f as. -- -- Intuitively, in an infinite f `TheseT` f `TheseT` f `TheseT` f -- ..., each of those infinite positions may have an f in -- them. However, because of the at-least-one nature of TheseT, we -- know we have at least one f at one position somewhere. -- -- A Steps f a has potentially many fs, each -- stored at a different Natural position, with the guaruntee that -- at least one f exists. -- -- Can be useful for using with the Monoidal instance of -- TheseT. -- -- interpreting it requires at least an Alt instance in the -- target context, since we have to handle potentially more than one -- f. -- -- This type is essentailly the same as NEMapF (Sum -- Natural) (except with a different Semigroup -- instance). newtype Steps f a Steps :: NEMap Natural (f a) -> Steps f a [getSteps] :: Steps f a -> NEMap Natural (f a) -- | The functor combinator that forgets all structure in the input. -- Ignores the input structure and stores no information. -- -- Acts like the "zero" with respect to functor combinator composition. -- --
-- ComposeT ProxyF f ~ ProxyF -- ComposeT f ProxyF ~ ProxyF ---- -- It can be injected into (losing all information), but it is -- impossible to ever retract or interpret it. -- -- This is essentially ConstF (). data ProxyF f a ProxyF :: ProxyF f a -- | Functor combinator that forgets all structure on the input, and -- instead stores a value of type e. -- -- Like ProxyF, acts like a "zero" with functor combinator -- composition. -- -- It can be injected into (losing all information), but it is -- impossible to ever retract or interpret it. data ConstF e f a ConstF :: e -> ConstF e f a [getConstF] :: ConstF e f a -> e data EnvT e (w :: Type -> Type) a EnvT :: e -> w a -> EnvT e a -- | The reader monad transformer, which adds a read-only environment to -- the given monad. -- -- The return function ignores the environment, while -- >>= passes the inherited environment to both -- subcomputations. newtype ReaderT r (m :: k -> Type) (a :: k) :: forall k. () => Type -> k -> Type -> k -> Type ReaderT :: (r -> m a) -> ReaderT r [runReaderT] :: ReaderT r -> r -> m a -- | An f a, along with a Bool flag -- --
-- Flagged f a ~ (Bool, f a) -- Flagged f ~ ((,) Bool) :.: f -- functor composition ---- -- Creation with inject or pure uses False as the -- boolean. -- -- You can think of it as an f a that is "flagged" with a -- boolean value, and that value can indicuate whether or not it is -- "pure" (made with inject or pure) as False, or -- "impure" (made from some other source) as True. However, -- False may be always created directly, of course, using the -- constructor. -- -- You can think of it like a Step that is either 0 or 1, as well. -- -- interpreting it requires no constraint on the target context. -- -- This type is equivalent (along with its instances) to: -- -- data Flagged f a Flagged :: Bool -> f a -> Flagged f a [flaggedFlag] :: Flagged f a -> Bool [flaggedVal] :: Flagged f a -> f a -- | The trivial monad transformer, which maps a monad to an equivalent -- monad. newtype IdentityT (f :: k -> Type) (a :: k) :: forall k. () => k -> Type -> k -> Type IdentityT :: f a -> IdentityT [runIdentityT] :: IdentityT -> f a -- | Void2 a b is uninhabited for all a and -- b. data Void2 a b -- | A simple way to inject/reject into any eventual typeclass. -- -- In a way, this is the "ultimate" multi-purpose Interpret -- instance. You can use this to inject an f into a free -- structure of any typeclass. If you want f to have a -- Monad instance, for example, just use -- --
-- inject :: f a -> Final Monad f a ---- -- When you want to eventually interpret out the data, use: -- --
-- interpret :: (f ~> g) -> Final c f a -> g a ---- -- Essentially, Final c is the "free c". Final -- Monad is the free Monad, etc. -- -- Final can theoretically replace Ap, Ap1, -- ListF, NonEmptyF, MaybeF, Free, -- Identity, Coyoneda, and other instances of -- FreeOf, if you don't care about being able to pattern match on -- explicit structure. -- -- However, it cannot replace Interpret instances that are not -- free structures, like Step, Steps, Backwards, -- etc. -- -- Note that this doesn't have instances for all the typeclasses -- you could lift things into; you probably have to define your own if -- you want to use Final c as an instance of -- c (using liftFinal0, liftFinal1, -- liftFinal2 for help). newtype Final c f a Final :: (forall g. c g => (forall x. f x -> g x) -> g a) -> Final c f a [runFinal] :: Final c f a -> forall g. c g => (forall x. f x -> g x) -> g a -- | A typeclass associating a free structure with the typeclass it is free -- on. -- -- This essentially lists instances of Interpret where a "trip" -- through Final will leave it unchanged. -- --
-- fromFree . toFree == id -- toFree . fromFree == id ---- -- This can be useful because Final doesn't have a concrete -- structure that you can pattern match on and inspect, but t -- might. This lets you work on a concrete structure if you desire. class Interpret t => FreeOf c t | t -> c fromFree :: FreeOf c t => t f ~> Final c f toFree :: (FreeOf c t, Functor f) => Final c f ~> t f fromFree :: (FreeOf c t, C t (Final c f)) => t f ~> Final c f toFree :: (FreeOf c t, c (t f)) => Final c f ~> t f -- | Composition of monad transformers. newtype ComposeT (f :: Type -> Type -> Type -> Type) (g :: Type -> Type -> Type -> Type) (m :: Type -> Type) a ComposeT :: f (g m) a -> ComposeT a [getComposeT] :: ComposeT a -> f (g m) a infixr 9 `ComposeT` infixr 9 `ComposeT` -- | The Day convolution of two covariant functors. data Day (f :: Type -> Type) (g :: Type -> Type) a [Day] :: forall (f :: Type -> Type) (g :: Type -> Type) a b c. () => f b -> g c -> (b -> c -> a) -> Day f g a -- | Products: encode multiple arguments to constructors data (:*:) (f :: k -> Type) (g :: k -> Type) (p :: k) :: forall k. () => k -> Type -> k -> Type -> k -> Type (:*:) :: f p -> g p -> (:*:) infixr 6 :*: infixr 6 :*: -- | outL for :*: actually does not require Functor. -- This is the more general version. prodOutL :: (f :*: g) ~> f -- | outR for :*: actually does not require Functor. -- This is the more general version. prodOutR :: (f :*: g) ~> g -- | Sums: encode choice between constructors data (:+:) (f :: k -> Type) (g :: k -> Type) (p :: k) :: forall k. () => k -> Type -> k -> Type -> k -> Type L1 :: f p -> (:+:) R1 :: g p -> (:+:) infixr 5 :+: -- | Void: used for datatypes without constructors data V1 (p :: k) :: forall k. () => k -> Type data These1 (f :: Type -> Type) (g :: Type -> Type) a This1 :: f a -> These1 a That1 :: g a -> These1 a These1 :: f a -> g a -> These1 a -- | Functor composition. Comp f g a is equivalent to f -- (g a), and the Comp pattern synonym is a way of getting -- the f (g a) in a Comp f g a. -- -- For example, Maybe (IO Bool) is -- Comp Maybe IO Bool. -- -- This is mostly useful for its typeclass instances: in particular, -- Functor, Applicative, HBifunctor, and -- Monoidal. -- -- This is essentially a version of :.: and Compose that -- allows for an HBifunctor instance. -- -- It is slightly less performant. Using comp . -- unComp every once in a while will concretize a Comp -- value (if you have Functor f) and remove some -- indirection if you have a lot of chained operations. -- -- The "free monoid" over Comp is Free, and the "free -- semigroup" over Comp is Free1. data Comp f g a -- | An HBifunctor that ignores its second input. Like a :+: -- with no R1/right branch. -- -- This is Joker from Data.Bifunctors.Joker, but given a -- more sensible name for its purpose. newtype LeftF f g a LeftF :: f a -> LeftF f g a [runLeftF] :: LeftF f g a -> f a -- | An HBifunctor that ignores its first input. Like a :+: -- with no L1/left branch. -- -- In its polykinded form (on f), it is essentially a -- higher-order version of Tagged. newtype RightF f g a RightF :: g a -> RightF f g a [runRightF] :: RightF f g a -> g a -- | An "HFunctor combinator" that enhances an HFunctor with -- the ability to hold a single f a. This is the higher-order -- analogue of Lift. -- -- You can think of it as a free Inject for any f. -- -- Note that HLift IdentityT is equivalent to -- EnvT Any. data HLift t f a HPure :: f a -> HLift t f a HOther :: t f a -> HLift t f a -- | An "HFunctor combinator" that turns an HFunctor into -- potentially infinite nestings of that HFunctor. -- -- An HFree t f a is either f a, t f a, -- t (t f) a, t (t (t f)) a, etc. -- -- This effectively turns t into a tree with t -- branches. -- -- One particularly useful usage is with MapF. For example if you -- had a data type representing a command line command parser: -- --
-- data Command a ---- -- You could represent "many possible named commands" using -- --
-- type Commands = MapF String Command ---- -- And you can represent multiple nested named commands using: -- --
-- type NestedCommands = HFree (MapF String) ---- -- This has an Interpret instance, but it can be more useful to -- use via direct pattern matching, or through -- --
-- foldHFree -- :: HBifunctor t -- => f ~> g -- -> t g ~> g -- -> HFree t f ~> g ---- -- which requires no extra constriant on g, and lets you -- consider each branch separately. -- -- This can be considered the higher-oder analogue of Free; it is -- the free HBind for any HFunctor t. -- -- Note that HFree IdentityT is equivalent to -- Step. data HFree t f a HReturn :: f a -> HFree t f a HJoin :: t (HFree t f) a -> HFree t f a -- | Turn Identity into any Applicative f. Can be -- useful as an argument to hmap, hbimap, or -- interpret. -- -- It is a more general form of generalize from mmorph. generalize :: Applicative f => Identity ~> f -- | Natural transformation from any functor f into Proxy. -- Can be useful for "zeroing out" a functor with hmap or -- hbimap or interpret. absorb :: f ~> Proxy