Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides helpers for building dependency injection environments composed of records.
It's not necessary when defining the record components themselves, in that case Dep.Has should suffice.
>>>
:{
type Logger :: (Type -> Type) -> Type newtype Logger d = Logger { info :: String -> d () } -- data Repository d = Repository { findById :: Int -> d (Maybe String) , putById :: Int -> String -> d () , insert :: String -> d Int } -- data Controller d = Controller { create :: d Int , append :: Int -> String -> d Bool , inspect :: Int -> d (Maybe String) } -- type EnvHKD :: (Type -> Type) -> (Type -> Type) -> Type data EnvHKD h m = EnvHKD { logger :: h (Logger m), repository :: h (Repository m), controller :: h (Controller m) } deriving stock Generic deriving anyclass (FieldsFindableByType, DemotableFieldNames, Phased) deriving via Autowired (EnvHKD Identity m) instance Autowireable r_ m (EnvHKD Identity m) => Has r_ m (EnvHKD Identity m) :}
The module also provides a monad transformer-less way of performing dependency
injection, by means of fixEnv
.
Synopsis
- class Has r_ (m :: Type -> Type) (env :: Type) | env -> m
- newtype TheDefaultFieldName (env :: Type) = TheDefaultFieldName env
- newtype TheFieldName (name :: Symbol) (env :: Type) = TheFieldName env
- class FieldsFindableByType (env :: Type) where
- type FindFieldByType env (r :: Type) :: Symbol
- newtype Autowired (env :: Type) = Autowired env
- type Autowireable r_ (m :: Type -> Type) (env :: Type) = HasField (FindFieldByType env (r_ m)) env (Identity (r_ m))
- class Phased (env_ :: (Type -> Type) -> (Type -> Type) -> Type) where
- traverseH :: forall (h :: Type -> Type) (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type). (Applicative f, Typeable f, Typeable g, Typeable h, Typeable m) => (forall x. h x -> f (g x)) -> env_ h m -> f (env_ g m)
- liftA2H :: forall (a :: Type -> Type) (f :: Type -> Type) (f' :: Type -> Type) (m :: Type -> Type). (Typeable a, Typeable f, Typeable f', Typeable m) => (forall x. a x -> f x -> f' x) -> env_ a m -> env_ f m -> env_ f' m
- pullPhase :: forall (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, Applicative f, Typeable f, Typeable g, Typeable m) => env_ (Compose f g) m -> f (env_ g m)
- mapPhase :: forall (f :: Type -> Type) (f' :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, Typeable f, Typeable f', Typeable g, Typeable m) => (forall x. f x -> f' x) -> env_ (Compose f g) m -> env_ (Compose f' g) m
- liftA2Phase :: forall (a :: Type -> Type) (f' :: Type -> Type) (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, Typeable a, Typeable f, Typeable f', Typeable g, Typeable m) => (forall x. a x -> f x -> f' x) -> env_ (Compose a g) m -> env_ (Compose f g) m -> env_ (Compose f' g) m
- class DemotableFieldNames env_ where
- demoteFieldNamesH :: (forall x. String -> h String x) -> env_ (h String) m
- demoteFieldNames :: forall env_ m. DemotableFieldNames env_ => env_ (Constant String) m
- mapPhaseWithFieldNames :: forall (f :: Type -> Type) (f' :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, DemotableFieldNames env_, Typeable f, Typeable f', Typeable g, Typeable m) => (forall x. String -> f x -> f' x) -> env_ (Compose f g) m -> env_ (Compose f' g) m
- bindPhase :: forall f g a b. Functor f => f a -> (a -> g b) -> Compose f g b
- skipPhase :: forall f g a. Applicative f => g a -> Compose f g a
- type family Bare x where ...
- fromBare :: Coercible phases (Bare phases) => Bare phases -> phases
- toBare :: Coercible phases (Bare phases) => phases -> Bare phases
- fixEnv :: (Phased env_, Typeable env_, Typeable m) => env_ (Constructor (env_ Identity m)) m -> env_ Identity m
- type Constructor (env :: Type) = (->) env `Compose` Identity
- constructor :: forall r_ m env. (env -> r_ m) -> Constructor env (r_ m)
- data InductiveEnv (rs :: [(Type -> Type) -> Type]) (h :: Type -> Type) (m :: Type -> Type) where
- AddDep :: forall r_ m rs h. h (r_ m) -> InductiveEnv rs h m -> InductiveEnv (r_ ': rs) h m
- EmptyEnv :: forall m h. InductiveEnv '[] h m
- addDep :: forall r_ m rs. r_ m -> InductiveEnv rs Identity m -> InductiveEnv (r_ ': rs) Identity m
- emptyEnv :: forall m. InductiveEnv '[] Identity m
- newtype Identity a = Identity {
- runIdentity :: a
- newtype Constant a (b :: k) = Constant {
- getConstant :: a
- newtype Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1) = Compose {
- getCompose :: f (g a)
A general-purpose Has
class Has r_ (m :: Type -> Type) (env :: Type) | env -> m Source #
A generic "Has" class. When partially applied to a parametrizable
record-of-functions r_
, produces a 2-place constraint
saying that the environment e
has the record r_
with effect monad m
.
The constraint can be used on its own, or with Control.Monad.Dep.Class.
Instances
(FieldsFindableByType (env_ m), HasField (FindFieldByType (env_ m) (r_ m)) (env_ m) u, Coercible u (r_ m)) => Has r_ m (Autowired (env_ m)) Source # | |
(Dep r_, HasField (DefaultFieldName r_) (env_ m) u, Coercible u (r_ m)) => Has r_ m (TheDefaultFieldName (env_ m)) Source # | |
Defined in Dep.Env dep :: TheDefaultFieldName (env_ m) -> r_ m Source # | |
(HasField name (env_ m) u, Coercible u (r_ m)) => Has r_ m (TheFieldName name (env_ m)) Source # | |
Defined in Dep.Env dep :: TheFieldName name (env_ m) -> r_ m Source # | |
InductiveEnvFind r_ m rs => Has r_ m (InductiveEnv rs Identity m) Source # | Works by searching on the list of types. |
Helpers for deriving Has
via the default field name
newtype TheDefaultFieldName (env :: Type) Source #
Helper for DerivingVia
HasField
instances.
It expects the component to have as field name the default fieldname
specified by Dep
.
This is the same behavior as the DefaultSignatures
implementation for
Has
, so maybe it doesn't make much sense to use it, except for
explicitness.
Instances
(Dep r_, HasField (DefaultFieldName r_) (env_ m) u, Coercible u (r_ m)) => Has r_ m (TheDefaultFieldName (env_ m)) Source # | |
Defined in Dep.Env dep :: TheDefaultFieldName (env_ m) -> r_ m Source # |
via arbitrary field name
newtype TheFieldName (name :: Symbol) (env :: Type) Source #
TheFieldName env |
via autowiring
class FieldsFindableByType (env :: Type) Source #
Class for getting the field name from the field's type.
The default implementation of FindFieldByType
requires a Generic
instance, but users can write their own implementations.
type FindFieldByType env (r :: Type) :: Symbol Source #
type FindFieldByType env r = FindFieldByType_ env r
newtype Autowired (env :: Type) Source #
Helper for DerivingVia
HasField
instances.
The fields are identified by their types.
It uses FindFieldByType
under the hood.
BEWARE: for large records with many components, this technique might incur in long compilation times.
Autowired env |
type Autowireable r_ (m :: Type -> Type) (env :: Type) = HasField (FindFieldByType env (r_ m)) env (Identity (r_ m)) Source #
Constraints required when DerivingVia
all possible instances of Has
in
a single definition.
This only works for environments where all the fields come wrapped in Data.Functor.Identity.
Managing phases
class Phased (env_ :: (Type -> Type) -> (Type -> Type) -> Type) where Source #
Class of 2-parameter environments for which the first parameter h
wraps
each field and corresponds to phases in the construction of the environment,
and the second parameter m
is the effect monad used by each component.
h
will typically be a composition of applicative functors, each one
representing a phase. We advance through the phases by "pulling out" the
outermost phase and running it in some way, until we are are left with a
Constructor
phase, which we can remove using fixEnv
.
Phased
resembles FunctorT, TraversableT and ApplicativeT from the barbies library. Phased
instances can be written in terms of them.
Nothing
:: forall (h :: Type -> Type) (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type). (Applicative f, Typeable f, Typeable g, Typeable h, Typeable m) | |
=> (forall x. h x -> f (g x)) | |
-> env_ h m | |
-> f (env_ g m) |
default traverseH :: forall (h :: Type -> Type) (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type). (Applicative f, Typeable f, Typeable g, Typeable h, Typeable m, Generic (env_ h m), Generic (env_ g m), GTraverseH h g (Rep (env_ h m)) (Rep (env_ g m))) => (forall x. h x -> f (g x)) -> env_ h m -> f (env_ g m) Source #
:: forall (a :: Type -> Type) (f :: Type -> Type) (f' :: Type -> Type) (m :: Type -> Type). (Typeable a, Typeable f, Typeable f', Typeable m) | |
=> (forall x. a x -> f x -> f' x) | |
-> env_ a m | |
-> env_ f m | |
-> env_ f' m |
Used to implement liftA2Phase
, typically you should use that function instead.
default liftA2H :: forall (a :: Type -> Type) (f :: Type -> Type) (f' :: Type -> Type) m. (Typeable a, Typeable f, Typeable f', Typeable m, Generic (env_ a m), Generic (env_ f m), Generic (env_ f' m), GLiftA2Phase a f f' (Rep (env_ a m)) (Rep (env_ f m)) (Rep (env_ f' m))) => (forall x. a x -> f x -> f' x) -> env_ a m -> env_ f m -> env_ f' m Source #
Instances
Phased (InductiveEnv rs) Source # | |
Defined in Dep.Env traverseH :: forall h f g (m :: Type -> Type). (Applicative f, Typeable f, Typeable g, Typeable h, Typeable m) => (forall x. h x -> f (g x)) -> InductiveEnv rs h m -> f (InductiveEnv rs g m) Source # liftA2H :: forall a f f' (m :: Type -> Type). (Typeable a, Typeable f, Typeable f', Typeable m) => (forall x. a x -> f x -> f' x) -> InductiveEnv rs a m -> InductiveEnv rs f m -> InductiveEnv rs f' m Source # |
:: forall (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, Applicative f, Typeable f, Typeable g, Typeable m) | |
=> env_ (Compose f g) m | |
-> f (env_ g m) |
Take the outermost phase wrapping each component and "pull it outwards", aggregating the phase's applicative effects.
>>>
:{
newtype Foo d = Foo {foo :: String -> d ()} deriving Generic makeIOFoo :: MonadIO m => Foo m makeIOFoo = Foo (liftIO . putStrLn) env :: InductiveEnv '[Foo] (IO `Compose` Constructor (InductiveEnv '[Foo] Identity IO)) IO env = EmptyEnv & AddDep @Foo (putStrLn "io phase" `bindPhase` \() -> constructor (\_ -> makeIOFoo)) ioOutside :: IO (InductiveEnv '[Foo] (Constructor (InductiveEnv '[Foo] Identity IO)) IO) ioOutside = pullPhase env :}
:: forall (f :: Type -> Type) (f' :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, Typeable f, Typeable f', Typeable g, Typeable m) | |
=> (forall x. f x -> f' x) | |
-> env_ (Compose f g) m | |
-> env_ (Compose f' g) m |
Modify the outermost phase wrapping each component.
>>>
:{
newtype Foo d = Foo {foo :: String -> d ()} deriving Generic makeIOFoo :: MonadIO m => Foo m makeIOFoo = Foo (liftIO . putStrLn) env :: InductiveEnv '[Foo] ((,) Int `Compose` Constructor String) IO env = EmptyEnv & AddDep @Foo ((2,()) `bindPhase` \() -> constructor (\_ -> makeIOFoo)) env' :: InductiveEnv '[Foo] ((,) String `Compose` Constructor String) IO env' = mapPhase (\(n,x) -> (show n,x)) env :}
:: forall (a :: Type -> Type) (f' :: Type -> Type) (f :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, Typeable a, Typeable f, Typeable f', Typeable g, Typeable m) | |
=> (forall x. a x -> f x -> f' x) | |
-> env_ (Compose a g) m | |
-> env_ (Compose f g) m | |
-> env_ (Compose f' g) m |
Combine two environments with a function that works on their outermost phases.
Working with field names
class DemotableFieldNames env_ where Source #
Class of 2-parameter environments for which it's possible to obtain the names of each field as values.
Nothing
demoteFieldNames :: forall env_ m. DemotableFieldNames env_ => env_ (Constant String) m Source #
Bring down the field names of the environment to the term level and store them in the accumulator of Data.Functor.Constant.
mapPhaseWithFieldNames Source #
:: forall (f :: Type -> Type) (f' :: Type -> Type) (g :: Type -> Type) (m :: Type -> Type) env_. (Phased env_, DemotableFieldNames env_, Typeable f, Typeable f', Typeable g, Typeable m) | |
=> (forall x. String -> f x -> f' x) | |
-> env_ (Compose f g) m | |
-> env_ (Compose f' g) m |
Modify the outermost phase wrapping each component, while having access to the field name of the component.
A typical usage is modifying a "parsing the configuration" phase so that each component looks into a different section of the global configuration field.
Constructing phases
bindPhase
and skipPhase
are small convenience functions to help build nested compositions of functors.
bindPhase :: forall f g a b. Functor f => f a -> (a -> g b) -> Compose f g b Source #
Use the result of the previous phase to build the next one.
Can be useful infix.
>>>
:{
type Phases = IO `Compose` IO `Compose` Identity phased :: Phases Int phased = pure 1 `bindPhase` \i1 -> pure 2 `bindPhase` \i2 -> Identity (i1 + i2) :}
skipPhase :: forall f g a. Applicative f => g a -> Compose f g a Source #
Don't do anything for the current phase, just wrap the next one.
>>>
:{
type Phases = IO `Compose` IO `Compose` Identity phased :: Phases Int phased = skipPhase $ skipPhase $ Identity 1 :}
fromBare
and toBare
are an alternative method to build nested compositions of functors, which relies on "coerce".
type family Bare x where ... Source #
This type family clears newtypes like Compose
, Identity
and Constant
from a composite type,
leaving you with a newtypeless nested type as result.
The idea is that it might be easier to construct values of the "bare" version of a composite type,
and later coerce them to the newtyped version using fromBare
.
This is mainly intended for defining the nested Applicative
"phases" of components that live in a Phased
environment. It's an alternative to functions like bindPhase
and skipPhase
.
fromBare :: Coercible phases (Bare phases) => Bare phases -> phases Source #
Convert a value from its bare version to the newtyped one, usually as a step
towards inserting it into a Phased
environment.
>>>
:{
type Phases = IO `Compose` IO `Compose` IO wrapped :: Phases Int = fromBare $ pure $ pure $ pure 3 :}
>>>
:{
type Phases = Constructor Int wrapped :: Phases Int wrapped = fromBare $ succ :}
>>>
:{
type Phases = IO `Compose` Constructor Int wrapped :: Phases Int wrapped = fromBare $ pure $ succ :}
toBare :: Coercible phases (Bare phases) => phases -> Bare phases Source #
Convert from the newtyped value to the bare one. fromBare
tends to be more useful.
Injecting dependencies by tying the knot
:: (Phased env_, Typeable env_, Typeable m) | |
=> env_ (Constructor (env_ Identity m)) m | Environment where each field is wrapped in a |
-> env_ Identity m | Fully constructed environment, ready for use. |
This is a method of performing dependency injection that doesn't require Control.Monad.Dep.DepT at all. In fact, it doesn't require the use of any monad transformer!
If we have a environment whose fields are functions that construct each component by searching for its dependencies in a "fully built" version of the environment, we can "tie the knot" to obtain the "fully built" environment. This works as long as there aren't any circular dependencies between components.
Think of it as a version of fix
that, instead of "tying" a single
function, ties a whole record of them.
The env_ (Constructor (env_ Identity m)) m
parameter might be the result of peeling
away successive layers of applicative functor composition using pullPhase
,
until only the wiring phase remains.
>>>
:{
newtype Foo d = Foo {foo :: String -> d ()} deriving Generic newtype Bar d = Bar {bar :: String -> d ()} deriving Generic makeIOFoo :: MonadIO m => Foo m makeIOFoo = Foo (liftIO . putStrLn) makeBar :: Has Foo m env => env -> Bar m makeBar (asCall -> call) = Bar (call foo) env :: InductiveEnv [Bar,Foo] (Constructor (InductiveEnv [Bar,Foo] Identity IO)) IO env = EmptyEnv & AddDep @Foo (constructor (\_ -> makeIOFoo)) & AddDep @Bar (constructor makeBar) envReady :: InductiveEnv [Bar,Foo] Identity IO envReady = fixEnv env :}
>>>
:{
bar (dep envReady) "this is bar" :} this is bar
type Constructor (env :: Type) = (->) env `Compose` Identity Source #
A phase with the effect of "constructing each component by reading its dependencies from a completed environment".
The Constructor
phase for an environment will typically be parameterized
with the environment itself.
constructor :: forall r_ m env. (env -> r_ m) -> Constructor env (r_ m) Source #
Turn an environment-consuming function into a Constructor
that can be slotted
into some field of a Phased
environment.
Inductive environment with anonymous fields
data InductiveEnv (rs :: [(Type -> Type) -> Type]) (h :: Type -> Type) (m :: Type -> Type) where Source #
An inductively constructed environment with anonymous fields.
Can be useful for simple tests. Also for converting Has
-based
components into functions that take their dependencies as separate
positional parameters.
makeController :: (Monad m, Has Logger m env, Has Repository m env) => env -> Controller m makeController = undefined makeControllerPositional :: Monad m => Logger m -> Repository m -> Controller m makeControllerPositional a b = makeController $ addDep @Logger a $ addDep @Repository b $ emptyEnv makeController' :: (Monad m, Has Logger m env, Has Repository m env) => env -> Controller m makeController' env = makeControllerPositional (dep env) (dep env)
AddDep :: forall r_ m rs h. h (r_ m) -> InductiveEnv rs h m -> InductiveEnv (r_ ': rs) h m | |
EmptyEnv :: forall m h. InductiveEnv '[] h m |
Instances
InductiveEnvFind r_ m rs => Has r_ m (InductiveEnv rs Identity m) Source # | Works by searching on the list of types. |
Phased (InductiveEnv rs) Source # | |
Defined in Dep.Env traverseH :: forall h f g (m :: Type -> Type). (Applicative f, Typeable f, Typeable g, Typeable h, Typeable m) => (forall x. h x -> f (g x)) -> InductiveEnv rs h m -> f (InductiveEnv rs g m) Source # liftA2H :: forall a f f' (m :: Type -> Type). (Typeable a, Typeable f, Typeable f', Typeable m) => (forall x. a x -> f x -> f' x) -> InductiveEnv rs a m -> InductiveEnv rs f m -> InductiveEnv rs f' m Source # |
addDep :: forall r_ m rs. r_ m -> InductiveEnv rs Identity m -> InductiveEnv (r_ ': rs) Identity m Source #
emptyEnv :: forall m. InductiveEnv '[] Identity m Source #
Re-exports
Identity functor and monad. (a non-strict monad)
Since: base-4.8.0.0
Identity | |
|
Instances
Constant functor.
Constant | |
|
Instances
newtype Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1) infixr 9 #
Right-to-left composition of functors. The composition of applicative functors is always applicative, but the composition of monads is not always a monad.
Compose infixr 9 | |
|
Instances
Functor f => Generic1 (Compose f g :: k -> Type) | Since: base-4.9.0.0 |
TestEquality f => TestEquality (Compose f g :: k2 -> Type) | The deduction (via generativity) that if Since: base-4.14.0.0 |
Defined in Data.Functor.Compose | |
(Functor f, Functor g) => Functor (Compose f g) | Since: base-4.9.0.0 |
(Applicative f, Applicative g) => Applicative (Compose f g) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose | |
(Foldable f, Foldable g) => Foldable (Compose f g) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose fold :: Monoid m => Compose f g m -> m # foldMap :: Monoid m => (a -> m) -> Compose f g a -> m # foldMap' :: Monoid m => (a -> m) -> Compose f g a -> m # foldr :: (a -> b -> b) -> b -> Compose f g a -> b # foldr' :: (a -> b -> b) -> b -> Compose f g a -> b # foldl :: (b -> a -> b) -> b -> Compose f g a -> b # foldl' :: (b -> a -> b) -> b -> Compose f g a -> b # foldr1 :: (a -> a -> a) -> Compose f g a -> a # foldl1 :: (a -> a -> a) -> Compose f g a -> a # toList :: Compose f g a -> [a] # null :: Compose f g a -> Bool # length :: Compose f g a -> Int # elem :: Eq a => a -> Compose f g a -> Bool # maximum :: Ord a => Compose f g a -> a # minimum :: Ord a => Compose f g a -> a # | |
(Traversable f, Traversable g) => Traversable (Compose f g) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose | |
(Eq1 f, Eq1 g) => Eq1 (Compose f g) | Since: base-4.9.0.0 |
(Ord1 f, Ord1 g) => Ord1 (Compose f g) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose | |
(Read1 f, Read1 g) => Read1 (Compose f g) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (Compose f g a) # liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [Compose f g a] # liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (Compose f g a) # liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [Compose f g a] # | |
(Show1 f, Show1 g) => Show1 (Compose f g) | Since: base-4.9.0.0 |
(Alternative f, Applicative g) => Alternative (Compose f g) | Since: base-4.9.0.0 |
(Eq1 f, Eq1 g, Eq a) => Eq (Compose f g a) | Since: base-4.9.0.0 |
(Typeable a, Typeable f, Typeable g, Typeable k1, Typeable k2, Data (f (g a))) => Data (Compose f g a) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g0. g0 -> c g0) -> Compose f g a -> c (Compose f g a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Compose f g a) # toConstr :: Compose f g a -> Constr # dataTypeOf :: Compose f g a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Compose f g a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Compose f g a)) # gmapT :: (forall b. Data b => b -> b) -> Compose f g a -> Compose f g a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Compose f g a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Compose f g a -> r # gmapQ :: (forall d. Data d => d -> u) -> Compose f g a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Compose f g a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Compose f g a -> m (Compose f g a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Compose f g a -> m (Compose f g a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Compose f g a -> m (Compose f g a) # | |
(Ord1 f, Ord1 g, Ord a) => Ord (Compose f g a) | Since: base-4.9.0.0 |
Defined in Data.Functor.Compose compare :: Compose f g a -> Compose f g a -> Ordering # (<) :: Compose f g a -> Compose f g a -> Bool # (<=) :: Compose f g a -> Compose f g a -> Bool # (>) :: Compose f g a -> Compose f g a -> Bool # (>=) :: Compose f g a -> Compose f g a -> Bool # | |
(Read1 f, Read1 g, Read a) => Read (Compose f g a) | Since: base-4.9.0.0 |
(Show1 f, Show1 g, Show a) => Show (Compose f g a) | Since: base-4.9.0.0 |
Generic (Compose f g a) | Since: base-4.9.0.0 |
type Rep1 (Compose f g :: k -> Type) | |
Defined in Data.Functor.Compose | |
type Rep (Compose f g a) | |
Defined in Data.Functor.Compose |