dep-t-advice-0.2.0.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 environment e must be parameterizable by a monad, and the type constructor 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 #

Aspects 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 (e (DepT e m)) (DepT e m) Source #

Ensure is a helper for lifting typeclass definitions of the form:

>>> :{
 type HasLogger :: Type -> (Type -> Type) -> Constraint
 class HasLogger em m | em -> m where
   logger :: em -> String -> m ()
:}

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 help with that. help with that.

restrictArgs takes as parameter evidence of entailment between ca constraints, using the type (:-) from the "constraints" package. But how to construct such evidence? By using the Sub and the Dict constructors, either with an explicit type signature:

>>> :{
 stricterPrintArgs :: forall e m r. MonadIO m => Advice (Show `And` Eq `And` Ord) NilEnv m r
 stricterPrintArgs = restrictArgs (Sub Dict) (printArgs stdout "foo")
:}

or with a type application to restrictArgs:

>>> stricterPrintArgs = restrictArgs @(Show `And` Eq `And` Ord) (Sub Dict) (printArgs stdout "foo")

restrictArgs Source #

Arguments

:: forall more less e m r. (forall x. more x :- less x)

Evidence that one constraint implies the other.

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

"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

"constraints" re-exports

Some useful definitions re-exported the from "constraints" package.

Dict and (:-) are GADTs used to capture and transform constraints. Used in the restrictArgs function.

newtype a :- b infixr 9 #

This is the type of entailment.

a :- b is read as a "entails" b.

With this we can actually build a category for Constraint resolution.

e.g.

Because Eq a is a superclass of Ord a, we can show that Ord a entails Eq a.

Because instance Ord a => Ord [a] exists, we can show that Ord a entails Ord [a] as well.

This relationship is captured in the :- entailment type here.

Since p :- p and entailment composes, :- forms the arrows of a Category of constraints. However, Category only became sufficiently general to support this instance in GHC 7.8, so prior to 7.8 this instance is unavailable.

But due to the coherence of instance resolution in Haskell, this Category has some very interesting properties. Notably, in the absence of IncoherentInstances, this category is "thin", which is to say that between any two objects (constraints) there is at most one distinguishable arrow.

This means that for instance, even though there are two ways to derive Ord a :- Eq [a], the answers from these two paths _must_ by construction be equal. This is a property that Haskell offers that is pretty much unique in the space of languages with things they call "type classes".

What are the two ways?

Well, we can go from Ord a :- Eq a via the superclass relationship, and then from Eq a :- Eq [a] via the instance, or we can go from Ord a :- Ord [a] via the instance then from Ord [a] :- Eq [a] through the superclass relationship and this diagram by definition must "commute".

Diagrammatically,

                   Ord a
               ins /     \ cls
                  v       v
            Ord [a]     Eq a
               cls \     / ins
                    v   v
                   Eq [a]

This safety net ensures that pretty much anything you can write with this library is sensible and can't break any assumptions on the behalf of library authors.

Constructors

Sub (a => Dict b) 

Instances

Instances details
Category (:-)

Possible since GHC 7.8, when Category was made polykinded.

Instance details

Defined in Data.Constraint

Methods

id :: forall (a :: k). a :- a #

(.) :: forall (b :: k) (c :: k) (a :: k). (b :- c) -> (a :- b) -> a :- c #

() :=> (Eq (a :- b)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Eq (a :- b) #

() :=> (Ord (a :- b)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Ord (a :- b) #

() :=> (Show (a :- b)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Show (a :- b) #

a => HasDict b (a :- b) 
Instance details

Defined in Data.Constraint

Methods

evidence :: (a :- b) -> Dict b #

Eq (a :- b)

Assumes IncoherentInstances doesn't exist.

Instance details

Defined in Data.Constraint

Methods

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

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

(Typeable p, Typeable q, p, q) => Data (p :- q) 
Instance details

Defined in Data.Constraint

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> (p :- q) -> c (p :- q) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (p :- q) #

toConstr :: (p :- q) -> Constr #

dataTypeOf :: (p :- q) -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (p :- q)) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (p :- q)) #

gmapT :: (forall b. Data b => b -> b) -> (p :- q) -> p :- q #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> (p :- q) -> r #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> (p :- q) -> r #

gmapQ :: (forall d. Data d => d -> u) -> (p :- q) -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> (p :- q) -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> (p :- q) -> m (p :- q) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> (p :- q) -> m (p :- q) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> (p :- q) -> m (p :- q) #

Ord (a :- b)

Assumes IncoherentInstances doesn't exist.

Instance details

Defined in Data.Constraint

Methods

compare :: (a :- b) -> (a :- b) -> Ordering #

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

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

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

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

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

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

Show (a :- b) 
Instance details

Defined in Data.Constraint

Methods

showsPrec :: Int -> (a :- b) -> ShowS #

show :: (a :- b) -> String #

showList :: [a :- b] -> ShowS #

a => NFData (a :- b) 
Instance details

Defined in Data.Constraint

Methods

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

data Dict a where #

Values of type Dict p capture a dictionary for a constraint of type p.

e.g.

Dict :: Dict (Eq Int)

captures a dictionary that proves we have an:

instance Eq 'Int

Pattern matching on the Dict constructor will bring this instance into scope.

Constructors

Dict :: forall a. a => Dict a 

Instances

Instances details
HasDict a (Dict a) 
Instance details

Defined in Data.Constraint

Methods

evidence :: Dict a -> Dict a #

a :=> (Read (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: a :- Read (Dict a) #

a :=> (Monoid (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: a :- Monoid (Dict a) #

a :=> (Enum (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: a :- Enum (Dict a) #

a :=> (Bounded (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: a :- Bounded (Dict a) #

() :=> (Eq (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Eq (Dict a) #

() :=> (Ord (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Ord (Dict a) #

() :=> (Show (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Show (Dict a) #

() :=> (Semigroup (Dict a)) 
Instance details

Defined in Data.Constraint

Methods

ins :: () :- Semigroup (Dict a) #

a => Bounded (Dict a) 
Instance details

Defined in Data.Constraint

Methods

minBound :: Dict a #

maxBound :: Dict a #

a => Enum (Dict a) 
Instance details

Defined in Data.Constraint

Methods

succ :: Dict a -> Dict a #

pred :: Dict a -> Dict a #

toEnum :: Int -> Dict a #

fromEnum :: Dict a -> Int #

enumFrom :: Dict a -> [Dict a] #

enumFromThen :: Dict a -> Dict a -> [Dict a] #

enumFromTo :: Dict a -> Dict a -> [Dict a] #

enumFromThenTo :: Dict a -> Dict a -> Dict a -> [Dict a] #

Eq (Dict a) 
Instance details

Defined in Data.Constraint

Methods

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

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

(Typeable p, p) => Data (Dict p) 
Instance details

Defined in Data.Constraint

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Dict p -> c (Dict p) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Dict p) #

toConstr :: Dict p -> Constr #

dataTypeOf :: Dict p -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Dict p)) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Dict p)) #

gmapT :: (forall b. Data b => b -> b) -> Dict p -> Dict p #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Dict p -> r #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Dict p -> r #

gmapQ :: (forall d. Data d => d -> u) -> Dict p -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Dict p -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Dict p -> m (Dict p) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Dict p -> m (Dict p) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Dict p -> m (Dict p) #

Ord (Dict a) 
Instance details

Defined in Data.Constraint

Methods

compare :: Dict a -> Dict a -> Ordering #

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

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

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

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

max :: Dict a -> Dict a -> Dict a #

min :: Dict a -> Dict a -> Dict a #

a => Read (Dict a) 
Instance details

Defined in Data.Constraint

Show (Dict a) 
Instance details

Defined in Data.Constraint

Methods

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

show :: Dict a -> String #

showList :: [Dict a] -> ShowS #

Semigroup (Dict a) 
Instance details

Defined in Data.Constraint

Methods

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

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

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

a => Monoid (Dict a) 
Instance details

Defined in Data.Constraint

Methods

mempty :: Dict a #

mappend :: Dict a -> Dict a -> Dict a #

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

NFData (Dict c) 
Instance details

Defined in Data.Constraint

Methods

rnf :: Dict c -> () #