Safe Haskell | None |
---|---|
Language | Haskell2010 |
This package provides the Advice
datatype, along for functions for creating,
manipulating, composing and applying values of that type.
Advice
s represent generic transformations on DepT
-effectful functions of
any number of arguments.
>>>
:{
foo0 :: DepT NilEnv IO (Sum Int) foo0 = pure (Sum 5) foo1 :: Bool -> DepT NilEnv IO (Sum Int) foo1 _ = foo0 foo2 :: Char -> Bool -> DepT NilEnv IO (Sum Int) foo2 _ = foo1 :}
They work for DepT
-actions of zero arguments:
>>>
advise (printArgs stdout "foo0") foo0 `runDepT` NilEnv
foo0: Sum {getSum = 5}
And for functions of one or more arguments, provided they end on a DepT
-action:
>>>
advise (printArgs stdout "foo1") foo1 False `runDepT` NilEnv
foo1: False Sum {getSum = 5}
>>>
advise (printArgs stdout "foo2") foo2 'd' False `runDepT` NilEnv
foo2: 'd' False Sum {getSum = 5}
Advice
s can also tweak the result value of functions:
>>>
advise (returnMempty @Top) foo2 'd' False `runDepT` NilEnv
Sum {getSum = 0}
And they can be combined using Advice
's Monoid
instance before being
applied:
>>>
advise (printArgs stdout "foo2" <> returnMempty) foo2 'd' False `runDepT` NilEnv
foo2: 'd' False Sum {getSum = 0}
Although sometimes composition might require harmonizing the constraints
each Advice
places on the arguments, if they differ.
Synopsis
- data Advice ca e_ m r
- makeAdvice :: forall u ca e_ m r. (forall as. All ca as => NP I as -> DepT e_ m (u, NP I as)) -> (u -> DepT e_ m r -> DepT e_ m r) -> Advice ca e_ m r
- makeArgsAdvice :: forall ca e_ m r. Monad m => (forall as. All ca as => NP I as -> DepT e_ m (NP I as)) -> Advice ca e_ m r
- makeExecutionAdvice :: forall ca e_ m r. Applicative m => (DepT e_ m r -> DepT e_ m r) -> Advice ca e_ m r
- advise :: forall ca e_ m r as advisee. (Multicurryable as e_ m r advisee, All ca as, Monad m) => Advice ca e_ m r -> advisee -> advisee
- type Ensure c e_ m = c (DepT e_ m) (e_ (DepT e_ m))
- restrictArgs :: forall more less e_ m r. (forall x. Dict more x -> Dict less x) -> Advice less e_ m r -> Advice more e_ m r
- runFinalDepT :: forall as e_ m r curried. Multicurryable as e_ m r curried => m (e_ (DepT e_ m)) -> curried -> DownToBaseMonad as e_ m r curried
- runFromEnv :: forall as e_ m r curried. Multicurryable as e_ m r curried => m (e_ (DepT e_ m)) -> (e_ (DepT e_ m) -> curried) -> DownToBaseMonad as e_ m r curried
- runFromDep :: forall dep as e_ m r curried. (Multicurryable as e_ m r curried, Has dep (DepT e_ m) (e_ (DepT e_ m))) => m (e_ (DepT e_ m)) -> (dep (DepT e_ m) -> curried) -> DownToBaseMonad as e_ m r curried
- deceive :: forall as e e_ m r curried. Gullible as e e_ m r curried => (e_ (DepT e_ m) -> e) -> NewtypedEnv as e e_ m r curried -> curried
- adviseRecord :: forall ca cr e_ m advised. AdvisedRecord ca e_ m cr advised => (forall r. cr r => [(TypeRep, String)] -> Advice ca e_ m r) -> advised (DepT e_ m) -> advised (DepT e_ m)
- deceiveRecord :: forall e e_ m gullible. GullibleRecord e e_ m gullible => (e_ (DepT e_ m) -> e) -> gullible (ReaderT e m) -> gullible (DepT e_ m)
- class Top (x :: k)
- class (f x, g x) => And (f :: k -> Constraint) (g :: k -> Constraint) (x :: k)
- class (AllF c xs, SListI xs) => All (c :: k -> Constraint) (xs :: [k])
- data NP (a :: k -> Type) (b :: [k]) where
- newtype I a = I a
- cfoldMap_NP :: forall k c (xs :: [k]) m proxy f. (All c xs, Monoid m) => proxy c -> (forall (a :: k). c a => f a -> m) -> NP f xs -> m
- data Dict (c :: k -> Constraint) (a :: k) where
- Dict :: forall k (c :: k -> Constraint) (a :: k). c a => Dict c a
The Advice type
data Advice ca e_ m r Source #
A generic transformation of DepT
-effectful functions with environment
e_
of kind (Type -> Type) -> Type
, base monad m
and return type r
,
provided the functions satisfy certain constraint ca
of kind Type ->
Constraint
on all of their arguments.
Note that the type constructor for the environment e_
is given unapplied.
That is, Advice Show NilEnv IO ()
kind-checks but Advice Show (NilEnv IO)
IO ()
doesn't. See also Ensure
.
Advice
s that don't care about the ca
constraint (because they don't
touch function arguments) can leave it polymorphic, and this facilitates
Advice
composition, but then the constraint must be given the catch-all
Top
value (using a type application) at the moment of calling advise
.
See Control.Monad.Dep.Advice.Basic for examples.
Instances
Monad m => Semigroup (Advice ca e_ m r) Source # |
The first |
Monad m => Monoid (Advice ca e_ m r) Source # | |
Creating Advice values
:: forall u ca e_ m r. (forall as. All ca as => NP I as -> DepT e_ m (u, NP I as)) | The function that tweaks the arguments. |
-> (u -> DepT e_ m r -> DepT e_ m r) | The function that tweaks the execution. |
-> Advice ca e_ m r |
The most general (and complex) way of constructing Advice
s.
Advice
s work in two phases. First, the arguments of the transformed
function are collected into an n-ary product NP
, and passed to the
first argument of makeAdvice
, which produces a (possibly transformed)
product of arguments, along with some summary value of type u
. Use ()
as the summary value if you don't care about it.
In the second phase, the monadic action produced by the function once all
arguments have been given is transformed using the second argument of
makeAdvice
. This second argument also receives the summary value of
type u
calculated earlier.
>>>
:{
doesNothing :: forall ca e_ m r. Monad m => Advice ca e_ m r doesNothing = makeAdvice @() (\args -> pure (pure args)) (\() action -> action) :}
TYPE APPLICATION REQUIRED! When invoking makeAdvice
, you must always give the
type of the existential u
through a type application. Otherwise you'll
get weird "u is untouchable" errors.
:: forall ca e_ m r. Monad m | |
=> (forall as. All ca as => NP I as -> DepT e_ m (NP I as)) | The function that tweaks the arguments. |
-> Advice ca e_ m r |
Create an advice which only tweaks and/or analyzes the function arguments.
Notice that there's no u
parameter, unlike with makeAdvice
.
>>>
:{
doesNothing :: forall ca e_ m r. Monad m => Advice ca e_ m r doesNothing = makeArgsAdvice pure :}
:: forall ca e_ m r. Applicative m | |
=> (DepT e_ m r -> DepT e_ m r) | The function that tweaks the execution. |
-> Advice ca e_ m r |
Create an advice which only tweaks the execution of the final monadic action.
Notice that there's no u
parameter, unlike with makeAdvice
.
>>>
:{
doesNothing :: forall ca e_ m r. Monad m => Advice ca e_ m r doesNothing = makeExecutionAdvice id :}
Applying Advices
:: forall ca e_ m r as advisee. (Multicurryable as e_ m r advisee, All ca as, Monad m) | |
=> Advice ca e_ m r | The advice to apply. |
-> advisee | A function to be adviced. |
-> advisee |
Apply an Advice
to some compatible function. The function must have its
effects in DepT
, and all of its arguments must satisfy the ca
constraint.
>>>
:{
foo :: Int -> DepT NilEnv IO String foo _ = pure "foo" advisedFoo = advise (printArgs stdout "Foo args: ") foo :}
TYPE APPLICATION REQUIRED! If the ca
constraint of the Advice
remains polymorphic,
it must be supplied by means of a type application:
>>>
:{
bar :: Int -> DepT NilEnv IO String bar _ = pure "bar" advisedBar1 = advise (returnMempty @Top) bar advisedBar2 = advise @Top returnMempty bar :}
Constraint helpers
To help with the constraint ca
that parameterizes Advice
, this library re-exports the following helpers from "sop-core":
Top
is the "always satisfied" constraint, useful when whe don't want to require anything specific inca
.And
combines two constraints so that anAdvice
can request them both, for exampleShow `And` Eq
.
Also, the All
constraint says that some constraint is satisfied by all the
components of an NP
product. It's in scope when processing the function
arguments inside an Advice
.
type Ensure c e_ m = c (DepT e_ m) (e_ (DepT e_ m)) Source #
Ensure
is a helper for lifting typeclass definitions of the form:
>>>
:{
type HasLogger :: (Type -> Type) -> Type -> Constraint class HasLogger d e | e -> d where logger :: e -> String -> d () :}
To work as a constraints on the e_
and m
parameters of an Advice
, like this:
>>>
:{
requiresLogger :: forall e_ m r. (Ensure HasLogger e_ m, Monad m) => Advice Show e_ m r requiresLogger = mempty :}
Why is it necessary? Two-place HasX
-style constraints receive the "fully
applied" type of the record-of-functions. That is: NilEnv IO
instead of
simply NilEnv
. This allows them to also work with monomorphic environments
(like those in RIO) whose type
isn't parameterized by any monad.
But the e_
type parameter of Advice
has kind (Type -> Type) -> Type
.
That is: NilEnv
alone.
Furthermore, Advices
require HasX
-style constraints to be placed on the
DepT
transformer, not directly on the base monad m
. Ensure
takes care
of that as well.
Harmonizing Advice argument constraints
Advice
values can be composed using the Monoid
instance, but only if
they have the same type parameters. It's unfortunate that—unlike with
normal function constraints—the ca
constraints of an Advice
aren't
automatically "collected" during composition.
Instead, we need to harmonize the ca
constraints of each Advice
by
turning them into the combination of all constraints. restrictArgs
helps with that.
restrictArgs
takes as parameter value-level "evidence" that one
constraint implies another. But how to construct such evidence? By using
the Dict
GADT, more precisely the deceptively simple-looking term
\Dict -> Dict
. That function "absorbs" some constraint present in the
ambient context and re-packages it a a new constraint that is implied by
the former. We can't rely on type inference here; we need to provide
enough type information to the GADT, be it as an explicit signature:
>>>
:{
stricterPrintArgs :: forall e_ m r. MonadIO m => Advice (Show `And` Eq `And` Ord) e_ m r stricterPrintArgs = restrictArgs (\Dict -> Dict) (printArgs stdout "foo") :}
or with a type application to restrictArgs
:
>>>
stricterPrintArgs = restrictArgs @(Show `And` Eq `And` Ord) (\Dict -> Dict) (printArgs stdout "foo")
:: forall more less e_ m r. (forall x. Dict more x -> Dict less x) | Evidence that one constraint implies the other. Every |
-> Advice less e_ m r | Advice with less restrictive constraint on the args. |
-> Advice more e_ m r | Advice with more restrictive constraint on the args. |
Makes the constraint on the arguments more restrictive.
Invocation helpers
These functions are helpers for running DepT
computations, beyond what runDepT
provides.
They aren't directly related to Advice
s, but they require some of the same machinery, and that's why they are here.
:: forall as e_ m r curried. Multicurryable as e_ m r curried | |
=> m (e_ (DepT e_ m)) | action that gets hold of the environment |
-> (e_ (DepT e_ m) -> curried) | gets a function from the environment with effects in |
-> DownToBaseMonad as e_ m r curried | a new function with effects in the base monad |
Given a base monad m
action that gets hold of the DepT
environment,
and a function capable of extracting a curried function from the
environment, run the DepT
transformer at the tip of the resulting curried
function.
Why put the environment behind the m
action? Well, since getting to the
end of the curried function takes some work, it's a good idea to have some
flexibility once we arrive there. For example, the environment could be
stored in a Data.IORef and change in response to events, perhaps with
advices being added or removed.
>>>
:{
type MutableEnv :: (Type -> Type) -> Type data MutableEnv m = MutableEnv { _foo :: Int -> m (Sum Int) } :}
>>>
:{
do envRef <- newIORef (MutableEnv (pure . Sum)) let foo' = runFromEnv (readIORef envRef) _foo do r <- foo' 7 print r modifyIORef envRef (\e -> e { _foo = advise @Top returnMempty (_foo e) }) do r <- foo' 7 print r :} Sum {getSum = 7} Sum {getSum = 0}
:: forall dep as e_ m r curried. (Multicurryable as e_ m r curried, Has dep (DepT e_ m) (e_ (DepT e_ m))) | |
=> m (e_ (DepT e_ m)) | action that gets hold of the environment |
-> (dep (DepT e_ m) -> curried) | selector that gets a function from a dependency found using |
-> DownToBaseMonad as e_ m r curried | a new function with effects in the base monad |
Like runFromEnv
, but the function to run is extracted from a dependency
dep
which is found using Has
. The selector should be concrete enough to
identify dep
in the environment.
Making functions see a different environment
:: forall as e e_ m r curried. Gullible as e e_ m r curried | |
=> (e_ (DepT e_ m) -> e) | The newtype constructor that masks the "true" environment. |
-> NewtypedEnv as e e_ m r curried | A function to be deceived. It must be polymorphic over |
-> curried | The deceived function, that has effects in |
Makes a function see a newtyped version of the environment record, a version that might have different HasX
instances.
The "deception" doesn't affect the dependencies used by the function, only the function itself.
For example, consider the following setup which features both a "deceviced" and an "undeceived" version of a controller function:
>>>
:{
type HasLogger :: (Type -> Type) -> Type -> Constraint class HasLogger d e | e -> d where logger :: e -> String -> d () type HasIntermediate :: (Type -> Type) -> Type -> Constraint class HasIntermediate d e | e -> d where intermediate :: e -> String -> d () type Env :: (Type -> Type) -> Type data Env m = Env { _logger1 :: String -> m (), _logger2 :: String -> m (), _intermediate :: String -> m (), _controllerA :: Int -> m (), _controllerB :: Int -> m () } instance HasLogger m (Env m) where logger = _logger1 instance HasIntermediate m (Env m) where intermediate = _intermediate newtype Switcheroo m = Switcheroo (Env m) deriving newtype (HasIntermediate m) instance HasLogger m (Switcheroo m) where logger (Switcheroo e) = _logger2 e env :: Env (DepT Env (Writer [String])) env = let mkController :: forall d e m. MonadDep [HasLogger, HasIntermediate] d e m => Int -> m () mkController _ = do e <- ask; liftD $ logger e "foo" ; liftD $ intermediate e "foo" mkIntermediate :: forall d e m. MonadDep '[HasLogger] d e m => String -> m () mkIntermediate _ = do e <- ask ; liftD $ logger e "foo" in Env { _logger1 = \_ -> tell ["logger 1"], _logger2 = \_ -> tell ["logger 2"], _intermediate = mkIntermediate, _controllerA = mkController, _controllerB = deceive Switcheroo $ mkController } :}
If we run _controllerA
the ouput is:
>>>
execWriter $ runFromEnv (pure env) _controllerA 7
["logger 1","logger 1"]
But if we run the "deceived" _controllerB
, we see that the function and its _intermediate
dependency use different loggers:
>>>
execWriter $ runFromEnv (pure env) _controllerB 7
["logger 2","logger 1"]
Note that the function that is "deceived" must be polymorphic over
MonadDep
. Passing a function whose effect monad has
already "collapsed" into DepT
won't work. Therefore, deceive
must be applied before any Advice
.
Advising and deceiving entire records
adviseRecord
and deceiveRecord
are versions of advise
and deceive
that, instead of working on bare
functions, transform entire records-of-functions in one go. They also work
with newtypes containing a single function. The records must derive Generic
.
Useful with the "wrapped" style of components facilitated by Control.Monad.Dep.Has
.
>>>
:{
type Logger :: (Type -> Type) -> Type newtype Logger d = Logger {log :: String -> d ()} deriving Generic type Repository :: (Type -> Type) -> Type data Repository d = Repository { select :: String -> d [Int], insert :: [Int] -> d () } deriving Generic type Controller :: (Type -> Type) -> Type newtype Controller d = Controller {serve :: Int -> d String} deriving Generic type Env :: (Type -> Type) -> Type data Env m = Env { logger :: Logger m, repository :: Repository m, controller :: Controller m } newtype Wraps x = Wraps x env :: Env (DepT Env (Writer ())) env = let logger = Logger \_ -> pure () repository = adviseRecord @Top @Top mempty $ deceiveRecord Wraps $ Repository {select = \_ -> pure [], insert = \_ -> pure ()} controller = adviseRecord @Top @Top mempty $ deceiveRecord Wraps $ Controller \_ -> pure "view" in Env {logger, repository, controller} :}
:: forall ca cr e_ m advised. AdvisedRecord ca e_ m cr advised | |
=> (forall r. cr r => [(TypeRep, String)] -> Advice ca e_ m r) | The advice to apply. |
-> advised (DepT e_ m) | The record to advise recursively. |
-> advised (DepT e_ m) | The advised record. |
Gives Advice
to all the functions in a record-of-functions.
The function that builds the advice receives a list of tuples (TypeRep, String)
which represent the record types and fields names we have
traversed until arriving at the advised function. This info can be useful for
logging advices. It's a list instead of a single tuple because
adviseRecord
works recursively.
TYPE APPLICATION REQUIRED! The ca
constraint on function arguments
and the cr
constraint on the result type must be supplied by means of a
type application. Supply Top
if no constraint is required.
:: forall e e_ m gullible. GullibleRecord e e_ m gullible | |
=> (e_ (DepT e_ m) -> e) | The newtype constructor that masks the "true" environment. |
-> gullible (ReaderT e m) | The record to deceive recursively. The monad parameter must be left polymorphic over |
-> gullible (DepT e_ m) | The deceived record. |
Makes an entire record-of-functions see a different version of the global environment record, a version that might have different HasX
instances.
deceiveRecord
must be applied before adviseRecord
.
"sop-core" re-exports
Some useful definitions re-exported the from "sop-core" package.
NP
is an n-ary product used to represent the arguments of advised functions.
I
is an identity functor. The arguments processed by an Advice
come wrapped in it.
cfoldMap_NP
is useful to construct homogeneous lists out of the NP
product, for example:
>>>
cfoldMap_NP (Proxy @Show) (\(I a) -> [show a]) (I False :* I (1::Int) :* Nil)
["False","1"]
A constraint that can always be satisfied.
Since: sop-core-0.2
Instances
Top (x :: k) | |
Defined in Data.SOP.Constraint |
class (f x, g x) => And (f :: k -> Constraint) (g :: k -> Constraint) (x :: k) infixl 7 #
Pairing of constraints.
Since: sop-core-0.2
Instances
(f x, g x) => And (f :: k -> Constraint) (g :: k -> Constraint) (x :: k) | |
Defined in Data.SOP.Constraint |
class (AllF c xs, SListI xs) => All (c :: k -> Constraint) (xs :: [k]) #
Require a constraint for every element of a list.
If you have a datatype that is indexed over a type-level
list, then you can use All
to indicate that all elements
of that type-level list must satisfy a given constraint.
Example: The constraint
All Eq '[ Int, Bool, Char ]
is equivalent to the constraint
(Eq Int, Eq Bool, Eq Char)
Example: A type signature such as
f :: All Eq xs => NP I xs -> ...
means that f
can assume that all elements of the n-ary
product satisfy Eq
.
Note on superclasses: ghc cannot deduce superclasses from All
constraints.
You might expect the following to compile
class (Eq a) => MyClass a foo :: (All Eq xs) => NP f xs -> z foo = [..] bar :: (All MyClass xs) => NP f xs -> x bar = foo
but it will fail with an error saying that it was unable to
deduce the class constraint
(or similar) in the
definition of AllF
Eq
xsbar
.
In cases like this you can use Dict
from Data.SOP.Dict
to prove conversions between constraints.
See this answer on SO for more details.
Instances
All (c :: k -> Constraint) ('[] :: [k]) | |
Defined in Data.SOP.Constraint cpara_SList :: proxy c -> r '[] -> (forall (y :: k0) (ys :: [k0]). (c y, All c ys) => r ys -> r (y ': ys)) -> r '[] # | |
(c x, All c xs) => All (c :: a -> Constraint) (x ': xs :: [a]) | |
Defined in Data.SOP.Constraint cpara_SList :: proxy c -> r '[] -> (forall (y :: k) (ys :: [k]). (c y, All c ys) => r ys -> r (y ': ys)) -> r (x ': xs) # |
data NP (a :: k -> Type) (b :: [k]) where #
An n-ary product.
The product is parameterized by a type constructor f
and
indexed by a type-level list xs
. The length of the list
determines the number of elements in the product, and if the
i
-th element of the list is of type x
, then the i
-th
element of the product is of type f x
.
The constructor names are chosen to resemble the names of the list constructors.
Two common instantiations of f
are the identity functor I
and the constant functor K
. For I
, the product becomes a
heterogeneous list, where the type-level list describes the
types of its components. For
, the product becomes a
homogeneous list, where the contents of the type-level list are
ignored, but its length still specifies the number of elements.K
a
In the context of the SOP approach to generic programming, an n-ary product describes the structure of the arguments of a single data constructor.
Examples:
I 'x' :* I True :* Nil :: NP I '[ Char, Bool ] K 0 :* K 1 :* Nil :: NP (K Int) '[ Char, Bool ] Just 'x' :* Nothing :* Nil :: NP Maybe '[ Char, Bool ]
Nil :: forall k (a :: k -> Type). NP a ('[] :: [k]) | |
(:*) :: forall k (a :: k -> Type) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x ': xs) infixr 5 |
Instances
HTrans (NP :: (k1 -> Type) -> [k1] -> Type) (NP :: (k2 -> Type) -> [k2] -> Type) | |
Defined in Data.SOP.NP htrans :: forall c (xs :: l1) (ys :: l2) proxy f g. AllZipN (Prod NP) c xs ys => proxy c -> (forall (x :: k10) (y :: k20). c x y => f x -> g y) -> NP f xs -> NP g ys # hcoerce :: forall (f :: k10 -> Type) (g :: k20 -> Type) (xs :: l1) (ys :: l2). AllZipN (Prod NP) (LiftedCoercible f g) xs ys => NP f xs -> NP g ys # | |
HPure (NP :: (k -> Type) -> [k] -> Type) | |
HAp (NP :: (k -> Type) -> [k] -> Type) | |
HCollapse (NP :: (k -> Type) -> [k] -> Type) | |
Defined in Data.SOP.NP | |
HTraverse_ (NP :: (k -> Type) -> [k] -> Type) | |
Defined in Data.SOP.NP hctraverse_ :: forall c (xs :: l) g proxy f. (AllN NP c xs, Applicative g) => proxy c -> (forall (a :: k0). c a => f a -> g ()) -> NP f xs -> g () # htraverse_ :: forall (xs :: l) g f. (SListIN NP xs, Applicative g) => (forall (a :: k0). f a -> g ()) -> NP f xs -> g () # | |
HSequence (NP :: (k -> Type) -> [k] -> Type) | |
Defined in Data.SOP.NP hsequence' :: forall (xs :: l) f (g :: k0 -> Type). (SListIN NP xs, Applicative f) => NP (f :.: g) xs -> f (NP g xs) # hctraverse' :: forall c (xs :: l) g proxy f f'. (AllN NP c xs, Applicative g) => proxy c -> (forall (a :: k0). c a => f a -> g (f' a)) -> NP f xs -> g (NP f' xs) # htraverse' :: forall (xs :: l) g f f'. (SListIN NP xs, Applicative g) => (forall (a :: k0). f a -> g (f' a)) -> NP f xs -> g (NP f' xs) # | |
All (Compose Eq f) xs => Eq (NP f xs) | |
(All (Compose Eq f) xs, All (Compose Ord f) xs) => Ord (NP f xs) | |
All (Compose Show f) xs => Show (NP f xs) | |
All (Compose Semigroup f) xs => Semigroup (NP f xs) | Since: sop-core-0.4.0.0 |
(All (Compose Monoid f) xs, All (Compose Semigroup f) xs) => Monoid (NP f xs) | Since: sop-core-0.4.0.0 |
All (Compose NFData f) xs => NFData (NP f xs) | Since: sop-core-0.2.5.0 |
Defined in Data.SOP.NP | |
type AllZipN (NP :: (k -> Type) -> [k] -> Type) (c :: a -> b -> Constraint) | |
Defined in Data.SOP.NP | |
type Same (NP :: (k1 -> Type) -> [k1] -> Type) | |
type Prod (NP :: (k -> Type) -> [k] -> Type) | |
type UnProd (NP :: (k -> Type) -> [k] -> Type) | |
type SListIN (NP :: (k -> Type) -> [k] -> Type) | |
Defined in Data.SOP.NP | |
type CollapseTo (NP :: (k -> Type) -> [k] -> Type) a | |
Defined in Data.SOP.NP | |
type AllN (NP :: (k -> Type) -> [k] -> Type) (c :: k -> Constraint) | |
Defined in Data.SOP.NP |
The identity type functor.
Like Identity
, but with a shorter name.
I a |
Instances
Monad I | |
Functor I | |
Applicative I | |
Foldable I | |
Defined in Data.SOP.BasicFunctors fold :: Monoid m => I m -> m # foldMap :: Monoid m => (a -> m) -> I a -> m # foldMap' :: Monoid m => (a -> m) -> I a -> m # foldr :: (a -> b -> b) -> b -> I a -> b # foldr' :: (a -> b -> b) -> b -> I a -> b # foldl :: (b -> a -> b) -> b -> I a -> b # foldl' :: (b -> a -> b) -> b -> I a -> b # foldr1 :: (a -> a -> a) -> I a -> a # foldl1 :: (a -> a -> a) -> I a -> a # elem :: Eq a => a -> I a -> Bool # maximum :: Ord a => I a -> a # | |
Traversable I | |
Eq1 I | Since: sop-core-0.2.4.0 |
Ord1 I | Since: sop-core-0.2.4.0 |
Defined in Data.SOP.BasicFunctors | |
Read1 I | Since: sop-core-0.2.4.0 |
Show1 I | Since: sop-core-0.2.4.0 |
NFData1 I | Since: sop-core-0.2.5.0 |
Defined in Data.SOP.BasicFunctors | |
Eq a => Eq (I a) | |
Ord a => Ord (I a) | |
Read a => Read (I a) | |
Show a => Show (I a) | |
Generic (I a) | |
Semigroup a => Semigroup (I a) | Since: sop-core-0.4.0.0 |
Monoid a => Monoid (I a) | Since: sop-core-0.4.0.0 |
NFData a => NFData (I a) | Since: sop-core-0.2.5.0 |
Defined in Data.SOP.BasicFunctors | |
type Rep (I a) | |
Defined in Data.SOP.BasicFunctors |
cfoldMap_NP :: forall k c (xs :: [k]) m proxy f. (All c xs, Monoid m) => proxy c -> (forall (a :: k). c a => f a -> m) -> NP f xs -> m #
Specialization of hcfoldMap
.
Since: sop-core-0.3.2.0
data Dict (c :: k -> Constraint) (a :: k) where #
An explicit dictionary carrying evidence of a class constraint.
The constraint parameter is separated into a
second argument so that
is of the correct
kind to be used directly as a parameter to e.g. Dict
cNP
.
Since: sop-core-0.2
Dict :: forall k (c :: k -> Constraint) (a :: k). c a => Dict c a |