| Copyright | (c) Justin Le 2019 |
|---|---|
| License | BSD3 |
| Maintainer | justin@jle.im |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Data.HFunctor
Description
This module provides abstractions for working with unary functor combinators.
Principally, it defines the HFunctor itself, as well as some classes
that expose extra functionality that some HFunctors have (Inject and
HBind).
See Data.HFunctor.Interpret for tools to use HFunctors as functor
combinators that can represent interpretable schemas, and
Data.HBifunctor for an abstraction over binary functor combinators.
Synopsis
- class HFunctor t where
- overHFunctor :: HFunctor t => (f <~> g) -> t f <~> t g
- class HFunctor t => Inject t where
- class Inject t => HBind t where
- data ProxyF f a = ProxyF
- data ConstF e f a = ConstF {
- getConstF :: e
- data HLift t f a
- retractHLift :: Inject t => HLift t f a -> t f a
- data HFree t f a
- foldHFree :: forall t f g. HFunctor t => (f ~> g) -> (t g ~> g) -> HFree t f ~> g
- retractHFree :: HBind t => HFree t f a -> t f a
- injectMap :: (Inject t, Functor f) => (a -> b) -> f a -> t f b
- injectContramap :: (Inject t, Contravariant f) => (a -> b) -> f b -> t f a
Documentation
class HFunctor t where Source #
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 into a Free f: a monad built over
Free gf 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.
This class is also found in the hschema library with the same name.
Methods
hmap :: (f ~> g) -> t f ~> t g Source #
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
hmapid== id
Essentially, t f adds some "extra structure" to f. hmap
must swap out the functor, without affecting the added structure.
For example, is essentially a list of ListF f af 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 is a way of formalizing this property.hmap id == id
Instances
overHFunctor :: HFunctor t => (f <~> g) -> t f <~> t g Source #
Lift an isomorphism over an HFunctor.
Essentailly, if f and g are isomorphic, then so are t f and t g.
class HFunctor t => Inject t where Source #
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.
Methods
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.
Instances
class Inject t => HBind t where Source #
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:
hbindinject==id
But hbind should also be associatiatve, in a way that makes
hjoin. hjoin = hjoin .hmaphjoin
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.
Methods
hbind :: (f ~> t g) -> t f ~> t g Source #
Bind a continuation to a t f into some context g.
hjoin :: t (t f) ~> t f Source #
Collapse a nested t (t f) into a single t f.
Instances
Simple instances
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.
ComposeTProxyF f ~ ProxyFComposeTf ProxyF ~ ProxyF
It can be injected into (losing all information), but it is impossible
to ever retract or
interpret it.
This is essentially .ConstF ()
Constructors
| ProxyF |
Instances
| HTraversable (ProxyF :: (k -> Type) -> k1 -> Type) Source # | |
Defined in Data.HFunctor.HTraversable | |
| HFunctor (ProxyF :: (k -> Type) -> k1 -> Type) Source # | |
| HBind (ProxyF :: (k -> Type) -> k -> Type) Source # | |
| Inject (ProxyF :: (k -> Type) -> k -> Type) Source # | |
| Foldable (ProxyF f :: TYPE LiftedRep -> Type) Source # | |
Defined in Data.HFunctor Methods fold :: Monoid m => ProxyF f m -> m # foldMap :: Monoid m => (a -> m) -> ProxyF f a -> m # foldMap' :: Monoid m => (a -> m) -> ProxyF f a -> m # foldr :: (a -> b -> b) -> b -> ProxyF f a -> b # foldr' :: (a -> b -> b) -> b -> ProxyF f a -> b # foldl :: (b -> a -> b) -> b -> ProxyF f a -> b # foldl' :: (b -> a -> b) -> b -> ProxyF f a -> b # foldr1 :: (a -> a -> a) -> ProxyF f a -> a # foldl1 :: (a -> a -> a) -> ProxyF f a -> a # elem :: Eq a => a -> ProxyF f a -> Bool # maximum :: Ord a => ProxyF f a -> a # minimum :: Ord a => ProxyF f a -> a # | |
| Eq1 (ProxyF f :: Type -> Type) Source # | |
| Ord1 (ProxyF f :: Type -> Type) Source # | |
Defined in Data.HFunctor | |
| Read1 (ProxyF f :: Type -> Type) Source # | |
Defined in Data.HFunctor | |
| Show1 (ProxyF f :: TYPE LiftedRep -> Type) Source # | |
| Contravariant (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Traversable (ProxyF f :: TYPE LiftedRep -> Type) Source # | |
| Functor (ProxyF f :: TYPE LiftedRep -> Type) Source # | |
| Decidable (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Divisible (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Conclude (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Decide (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Divise (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Invariant (ProxyF f :: Type -> Type) Source # | Since: 0.3.0.0 |
Defined in Data.HFunctor | |
| (Typeable f, Typeable a, Typeable k1, Typeable k2) => Data (ProxyF f a) Source # | |
Defined in Data.HFunctor Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ProxyF f a -> c (ProxyF f a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (ProxyF f a) # toConstr :: ProxyF f a -> Constr # dataTypeOf :: ProxyF f a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (ProxyF f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (ProxyF f a)) # gmapT :: (forall b. Data b => b -> b) -> ProxyF f a -> ProxyF f a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ProxyF f a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ProxyF f a -> r # gmapQ :: (forall d. Data d => d -> u) -> ProxyF f a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ProxyF f a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ProxyF f a -> m (ProxyF f a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ProxyF f a -> m (ProxyF f a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ProxyF f a -> m (ProxyF f a) # | |
| Generic (ProxyF f a) Source # | |
| Read (ProxyF f a) Source # | |
| Show (ProxyF f a) Source # | |
| Eq (ProxyF f a) Source # | |
| Ord (ProxyF f a) Source # | |
| type Rep (ProxyF f a) Source # | |
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.
Instances
| HTraversable (ConstF e :: (k -> Type) -> k1 -> Type) Source # | |
Defined in Data.HFunctor.HTraversable | |
| HFunctor (ConstF e :: (k -> Type) -> k1 -> Type) Source # | |
| Monoid e => Inject (ConstF e :: (k -> Type) -> k -> Type) Source # | |
| Foldable (ConstF e f :: TYPE LiftedRep -> Type) Source # | |
Defined in Data.HFunctor Methods fold :: Monoid m => ConstF e f m -> m # foldMap :: Monoid m => (a -> m) -> ConstF e f a -> m # foldMap' :: Monoid m => (a -> m) -> ConstF e f a -> m # foldr :: (a -> b -> b) -> b -> ConstF e f a -> b # foldr' :: (a -> b -> b) -> b -> ConstF e f a -> b # foldl :: (b -> a -> b) -> b -> ConstF e f a -> b # foldl' :: (b -> a -> b) -> b -> ConstF e f a -> b # foldr1 :: (a -> a -> a) -> ConstF e f a -> a # foldl1 :: (a -> a -> a) -> ConstF e f a -> a # toList :: ConstF e f a -> [a] # null :: ConstF e f a -> Bool # length :: ConstF e f a -> Int # elem :: Eq a => a -> ConstF e f a -> Bool # maximum :: Ord a => ConstF e f a -> a # minimum :: Ord a => ConstF e f a -> a # | |
| Eq e => Eq1 (ConstF e f :: Type -> Type) Source # | |
| Ord e => Ord1 (ConstF e f :: Type -> Type) Source # | |
Defined in Data.HFunctor | |
| Read e => Read1 (ConstF e f :: Type -> Type) Source # | |
Defined in Data.HFunctor Methods liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (ConstF e f a) # liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [ConstF e f a] # liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (ConstF e f a) # liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [ConstF e f a] # | |
| Show e => Show1 (ConstF e f :: TYPE LiftedRep -> Type) Source # | |
| Contravariant (ConstF e f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Traversable (ConstF e f :: TYPE LiftedRep -> Type) Source # | |
Defined in Data.HFunctor | |
| Functor (ConstF e f :: TYPE LiftedRep -> Type) Source # | |
| Monoid e => Divisible (ConstF e f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Semigroup e => Divise (ConstF e f :: Type -> Type) Source # | Since: 0.3.0.0 |
| Invariant (ConstF e f :: Type -> Type) Source # | Since: 0.3.0.0 |
Defined in Data.HFunctor | |
| (Typeable f, Typeable a, Typeable k1, Typeable k2, Data e) => Data (ConstF e f a) Source # | |
Defined in Data.HFunctor Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ConstF e f a -> c (ConstF e f a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (ConstF e f a) # toConstr :: ConstF e f a -> Constr # dataTypeOf :: ConstF e f a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (ConstF e f a)) # dataCast2 :: Typeable t => (forall d e0. (Data d, Data e0) => c (t d e0)) -> Maybe (c (ConstF e f a)) # gmapT :: (forall b. Data b => b -> b) -> ConstF e f a -> ConstF e f a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ConstF e f a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ConstF e f a -> r # gmapQ :: (forall d. Data d => d -> u) -> ConstF e f a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ConstF e f a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ConstF e f a -> m (ConstF e f a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ConstF e f a -> m (ConstF e f a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ConstF e f a -> m (ConstF e f a) # | |
| Generic (ConstF e f a) Source # | |
| Read e => Read (ConstF e f a) Source # | |
| Show e => Show (ConstF e f a) Source # | |
| Eq e => Eq (ConstF e f a) Source # | |
| Ord e => Ord (ConstF e f a) Source # | |
Defined in Data.HFunctor | |
| type Rep (ConstF e f a) Source # | |
Defined in Data.HFunctor | |
HFunctor Combinators
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.
Instances
| HTraversable t => HTraversable (HLift t :: (k1 -> Type) -> k1 -> Type) Source # | |
Defined in Data.HFunctor.HTraversable | |
| HTraversable1 t => HTraversable1 (HLift t :: (k1 -> Type) -> k1 -> Type) Source # | |
Defined in Data.HFunctor.HTraversable | |
| HFunctor t => HFunctor (HLift t :: (k1 -> Type) -> k1 -> Type) Source # | |
| HBind t => HBind (HLift t :: (k -> Type) -> k -> Type) Source # | |
| HFunctor t => Inject (HLift t :: (k -> Type) -> k -> Type) Source # | |
| Interpret t f => Interpret (HLift t :: (k -> Type) -> k -> Type) (f :: k -> Type) Source # | Never uses |
| (Eq1 (t f), Eq1 f) => Eq1 (HLift t f) Source # | |
| (Ord1 (t f), Ord1 f) => Ord1 (HLift t f) Source # | |
Defined in Data.HFunctor | |
| (Show1 (t f), Show1 f) => Show1 (HLift t f) Source # | |
| (Contravariant f, Contravariant (t f)) => Contravariant (HLift t f) Source # | Since: 0.3.0.0 |
| (Functor f, Functor (t f)) => Functor (HLift t f) Source # | |
| (Invariant f, Invariant (t f)) => Invariant (HLift t f) Source # | Since: 0.3.0.0 |
Defined in Data.HFunctor | |
| (Read (f a), Read (t f a)) => Read (HLift t f a) Source # | |
| (Show (f a), Show (t f a)) => Show (HLift t f a) Source # | |
| (Eq (f a), Eq (t f a)) => Eq (HLift t f a) Source # | |
| (Ord (f a), Ord (t f a)) => Ord (HLift t f a) Source # | |
Defined in Data.HFunctor | |
retractHLift :: Inject t => HLift t f a -> t f a Source #
An "HFunctor combinator" that turns an HFunctor into potentially
infinite nestings of that HFunctor.
An is either HFree t f af 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 =MapFStringCommand
And you can represent multiple nested named commands using:
type NestedCommands =HFree(MapFString)
This has an Interpret instance, but it can be
more useful to use via direct pattern matching, or through
foldHFree::HBifunctort => 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
Instances
| HTraversable t => HTraversable (HFree t :: (k1 -> Type) -> k1 -> Type) Source # | |
Defined in Data.HFunctor.HTraversable | |
| HTraversable1 t => HTraversable1 (HFree t :: (k1 -> Type) -> k1 -> Type) Source # | |
Defined in Data.HFunctor.HTraversable | |
| HFunctor t => HFunctor (HFree t :: (k1 -> Type) -> k1 -> Type) Source # | |
| HFunctor t => HBind (HFree t :: (k -> Type) -> k -> Type) Source # | |
| HFunctor t => Inject (HFree t :: (k -> Type) -> k -> Type) Source # | |
| Interpret t f => Interpret (HFree t :: (k -> Type) -> k -> Type) (f :: k -> Type) Source # | Never uses |
| (Show1 (t (HFree t f)), Show1 f) => Show1 (HFree t f) Source # | |
| (Contravariant f, Contravariant (t (HFree t f))) => Contravariant (HFree t f) Source # | |
| (Functor f, Functor (t (HFree t f))) => Functor (HFree t f) Source # | |
| (Invariant f, Invariant (t (HFree t f))) => Invariant (HFree t f) Source # | |
Defined in Data.HFunctor | |
| (Show1 (t (HFree t f)), Show1 f, Show a) => Show (HFree t f a) Source # | |
retractHFree :: HBind t => HFree t f a -> t f a Source #
Utility functions
injectMap :: (Inject t, Functor f) => (a -> b) -> f a -> t f b Source #
A useful wrapper over the common pattern of fmap-before-inject/inject-and-fmap.
Since: 0.3.3.0
injectContramap :: (Inject t, Contravariant f) => (a -> b) -> f b -> t f a Source #
A useful wrapper over the common pattern of contramap-before-inject/inject-and-contramap.
Since: 0.3.3.0