dep-t-advice-0.4.4.0: Giving good advice to functions in a DepT environment.
Safe HaskellNone
LanguageHaskell2010

Control.Monad.Dep.Advice

Description

This package provides the Advice datatype, along for functions for creating, manipulating, composing and applying values of that type.

Advices 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}

Advices 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

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.

Advices 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

Instances details
Monad m => Semigroup (Advice ca e_ m r) Source #

Advices compose "sequentially" when tweaking the arguments, and "concentrically" when tweaking the final DepT action.

The first Advice is the "outer" one. It tweaks the function arguments first, and wraps around the execution of the second, "inner" Advice.

Instance details

Defined in Control.Monad.Dep.Advice

Methods

(<>) :: Advice ca e_ m r -> Advice ca e_ m r -> Advice ca e_ m r #

sconcat :: NonEmpty (Advice ca e_ m r) -> Advice ca e_ m r #

stimes :: Integral b => b -> Advice ca e_ m r -> Advice ca e_ m r #

Monad m => Monoid (Advice ca e_ m r) Source # 
Instance details

Defined in Control.Monad.Dep.Advice

Methods

mempty :: Advice ca e_ m r #

mappend :: Advice ca e_ m r -> Advice ca e_ m r -> Advice ca e_ m r #

mconcat :: [Advice ca e_ m r] -> Advice ca e_ m r #

Creating Advice values

makeAdvice Source #

Arguments

:: 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 Advices.

Advices 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.

makeArgsAdvice Source #

Arguments

:: 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
:}

makeExecutionAdvice Source #

Arguments

:: 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

advise Source #

Arguments

:: 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 in ca.
  • And combines two constraints so that an Advice can request them both, for example Show `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")

restrictArgs Source #

Arguments

:: forall more less e_ m r. (forall x. Dict more x -> Dict less x)

Evidence that one constraint implies the other. Every x that has a more instance also has a less instance.

-> 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 Advices, but they require some of the same machinery, and that's why they are here.

runFinalDepT Source #

Arguments

:: forall as e_ m r curried. Multicurryable as e_ m r curried 
=> m (e_ (DepT e_ m))

action that gets hold of the environment

-> curried

function to invoke with effects in DepT

-> 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, run the DepT transformer at the tip of a curried function.

>>> :{
 foo :: Int -> Int -> Int -> DepT NilEnv IO ()
 foo _ _ _ = pure ()
:}
>>> runFinalDepT (pure NilEnv) foo 1 2 3 :: IO ()

runFromEnv Source #

Arguments

:: 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 DepT

-> 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}

Making functions see a different environment

deceive Source #

Arguments

:: 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 MonadDep.

-> curried

The deceived function, that has effects in DepT.

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

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}
:}

adviseRecord Source #

Arguments

:: forall ca cr e_ m advised. AdvisedRecord ca e_ m cr advised 
=> (forall r f. (cr r, Foldable f) => f (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.

deceiveRecord Source #

Arguments

:: 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 MonadDep, so that it can unify with ReaderT.

-> gullible (DepT e_ m)

The deceived record.

Makes an entire record-of-functions see a different version of the glooal 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"]

class Top (x :: k) #

A constraint that can always be satisfied.

Since: sop-core-0.2

Instances

Instances details
Top (x :: k) 
Instance details

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

Instances details
(f x, g x) => And (f :: k -> Constraint) (g :: k -> Constraint) (x :: k) 
Instance details

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 AllF Eq xs (or similar) in the definition of bar. 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.

Minimal complete definition

cpara_SList

Instances

Instances details
All (c :: k -> Constraint) ('[] :: [k]) 
Instance details

Defined in Data.SOP.Constraint

Methods

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]) 
Instance details

Defined in Data.SOP.Constraint

Methods

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 K a, 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.

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 ]

Constructors

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

Instances details
HTrans (NP :: (k1 -> Type) -> [k1] -> Type) (NP :: (k2 -> Type) -> [k2] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

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) 
Instance details

Defined in Data.SOP.NP

Methods

hpure :: forall (xs :: l) f. SListIN NP xs => (forall (a :: k0). f a) -> NP f xs #

hcpure :: forall c (xs :: l) proxy f. AllN NP c xs => proxy c -> (forall (a :: k0). c a => f a) -> NP f xs #

HAp (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hap :: forall (f :: k0 -> Type) (g :: k0 -> Type) (xs :: l). Prod NP (f -.-> g) xs -> NP f xs -> NP g xs #

HCollapse (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hcollapse :: forall (xs :: l) a. SListIN NP xs => NP (K a) xs -> CollapseTo NP a #

HTraverse_ (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

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) 
Instance details

Defined in Data.SOP.NP

Methods

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) 
Instance details

Defined in Data.SOP.NP

Methods

(==) :: NP f xs -> NP f xs -> Bool #

(/=) :: NP f xs -> NP f xs -> Bool #

(All (Compose Eq f) xs, All (Compose Ord f) xs) => Ord (NP f xs) 
Instance details

Defined in Data.SOP.NP

Methods

compare :: NP f xs -> NP f xs -> Ordering #

(<) :: NP f xs -> NP f xs -> Bool #

(<=) :: NP f xs -> NP f xs -> Bool #

(>) :: NP f xs -> NP f xs -> Bool #

(>=) :: NP f xs -> NP f xs -> Bool #

max :: NP f xs -> NP f xs -> NP f xs #

min :: NP f xs -> NP f xs -> NP f xs #

All (Compose Show f) xs => Show (NP f xs) 
Instance details

Defined in Data.SOP.NP

Methods

showsPrec :: Int -> NP f xs -> ShowS #

show :: NP f xs -> String #

showList :: [NP f xs] -> ShowS #

All (Compose Semigroup f) xs => Semigroup (NP f xs)

Since: sop-core-0.4.0.0

Instance details

Defined in Data.SOP.NP

Methods

(<>) :: NP f xs -> NP f xs -> NP f xs #

sconcat :: NonEmpty (NP f xs) -> NP f xs #

stimes :: Integral b => b -> NP f xs -> NP f xs #

(All (Compose Monoid f) xs, All (Compose Semigroup f) xs) => Monoid (NP f xs)

Since: sop-core-0.4.0.0

Instance details

Defined in Data.SOP.NP

Methods

mempty :: NP f xs #

mappend :: NP f xs -> NP f xs -> NP f xs #

mconcat :: [NP f xs] -> NP f xs #

All (Compose NFData f) xs => NFData (NP f xs)

Since: sop-core-0.2.5.0

Instance details

Defined in Data.SOP.NP

Methods

rnf :: NP f xs -> () #

type AllZipN (NP :: (k -> Type) -> [k] -> Type) (c :: a -> b -> Constraint) 
Instance details

Defined in Data.SOP.NP

type AllZipN (NP :: (k -> Type) -> [k] -> Type) (c :: a -> b -> Constraint) = AllZip c
type Same (NP :: (k1 -> Type) -> [k1] -> Type) 
Instance details

Defined in Data.SOP.NP

type Same (NP :: (k1 -> Type) -> [k1] -> Type) = NP :: (k2 -> Type) -> [k2] -> Type
type Prod (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

type Prod (NP :: (k -> Type) -> [k] -> Type) = NP :: (k -> Type) -> [k] -> Type
type UnProd (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NS

type UnProd (NP :: (k -> Type) -> [k] -> Type) = NS :: (k -> Type) -> [k] -> Type
type SListIN (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

type SListIN (NP :: (k -> Type) -> [k] -> Type) = SListI :: [k] -> Constraint
type CollapseTo (NP :: (k -> Type) -> [k] -> Type) a 
Instance details

Defined in Data.SOP.NP

type CollapseTo (NP :: (k -> Type) -> [k] -> Type) a = [a]
type AllN (NP :: (k -> Type) -> [k] -> Type) (c :: k -> Constraint) 
Instance details

Defined in Data.SOP.NP

type AllN (NP :: (k -> Type) -> [k] -> Type) (c :: k -> Constraint) = All c

newtype I a #

The identity type functor.

Like Identity, but with a shorter name.

Constructors

I a 

Instances

Instances details
Monad I 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

(>>=) :: I a -> (a -> I b) -> I b #

(>>) :: I a -> I b -> I b #

return :: a -> I a #

Functor I 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

fmap :: (a -> b) -> I a -> I b #

(<$) :: a -> I b -> I a #

Applicative I 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

pure :: a -> I a #

(<*>) :: I (a -> b) -> I a -> I b #

liftA2 :: (a -> b -> c) -> I a -> I b -> I c #

(*>) :: I a -> I b -> I b #

(<*) :: I a -> I b -> I a #

Foldable I 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

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 #

toList :: I a -> [a] #

null :: I a -> Bool #

length :: I a -> Int #

elem :: Eq a => a -> I a -> Bool #

maximum :: Ord a => I a -> a #

minimum :: Ord a => I a -> a #

sum :: Num a => I a -> a #

product :: Num a => I a -> a #

Traversable I 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

traverse :: Applicative f => (a -> f b) -> I a -> f (I b) #

sequenceA :: Applicative f => I (f a) -> f (I a) #

mapM :: Monad m => (a -> m b) -> I a -> m (I b) #

sequence :: Monad m => I (m a) -> m (I a) #

Eq1 I

Since: sop-core-0.2.4.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

liftEq :: (a -> b -> Bool) -> I a -> I b -> Bool #

Ord1 I

Since: sop-core-0.2.4.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

liftCompare :: (a -> b -> Ordering) -> I a -> I b -> Ordering #

Read1 I

Since: sop-core-0.2.4.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (I a) #

liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [I a] #

liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (I a) #

liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [I a] #

Show1 I

Since: sop-core-0.2.4.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> I a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [I a] -> ShowS #

NFData1 I

Since: sop-core-0.2.5.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

liftRnf :: (a -> ()) -> I a -> () #

Eq a => Eq (I a) 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

(==) :: I a -> I a -> Bool #

(/=) :: I a -> I a -> Bool #

Ord a => Ord (I a) 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

compare :: I a -> I a -> Ordering #

(<) :: I a -> I a -> Bool #

(<=) :: I a -> I a -> Bool #

(>) :: I a -> I a -> Bool #

(>=) :: I a -> I a -> Bool #

max :: I a -> I a -> I a #

min :: I a -> I a -> I a #

Read a => Read (I a) 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

readsPrec :: Int -> ReadS (I a) #

readList :: ReadS [I a] #

readPrec :: ReadPrec (I a) #

readListPrec :: ReadPrec [I a] #

Show a => Show (I a) 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

showsPrec :: Int -> I a -> ShowS #

show :: I a -> String #

showList :: [I a] -> ShowS #

Generic (I a) 
Instance details

Defined in Data.SOP.BasicFunctors

Associated Types

type Rep (I a) :: Type -> Type #

Methods

from :: I a -> Rep (I a) x #

to :: Rep (I a) x -> I a #

Semigroup a => Semigroup (I a)

Since: sop-core-0.4.0.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

(<>) :: I a -> I a -> I a #

sconcat :: NonEmpty (I a) -> I a #

stimes :: Integral b => b -> I a -> I a #

Monoid a => Monoid (I a)

Since: sop-core-0.4.0.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

mempty :: I a #

mappend :: I a -> I a -> I a #

mconcat :: [I a] -> I a #

NFData a => NFData (I a)

Since: sop-core-0.2.5.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

rnf :: I a -> () #

type Rep (I a) 
Instance details

Defined in Data.SOP.BasicFunctors

type Rep (I a) = D1 ('MetaData "I" "Data.SOP.BasicFunctors" "sop-core-0.5.0.1-LSgc1wfRk3m3wHkiLjj5ug" 'True) (C1 ('MetaCons "I" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 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 #

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 Dict c is of the correct kind to be used directly as a parameter to e.g. NP.

Since: sop-core-0.2

Constructors

Dict :: forall k (c :: k -> Constraint) (a :: k). c a => Dict c a 

Instances

Instances details
Show (Dict c a) 
Instance details

Defined in Data.SOP.Dict

Methods

showsPrec :: Int -> Dict c a -> ShowS #

show :: Dict c a -> String #

showList :: [Dict c a] -> ShowS #