dep-t-advice-0.6.2.0: Giving good advice to functions in records-of-functions.
Safe HaskellSafe-Inferred
LanguageHaskell2010

Dep.IOAdvice

Description

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

Advices are type-preserving transformations on IO-effectful functions of any number of arguments.

>>> :{
   foo0 :: IO (Sum Int)
   foo0 = pure (Sum 5)
   foo1 :: Bool -> IO (Sum Int)
   foo1 _ = foo0
   foo2 :: Char -> Bool -> IO (Sum Int)
   foo2 _ = foo1
:}

They work for IO-actions of zero arguments:

>>> advise (printArgs stdout "foo0") foo0
foo0:

Sum {getSum = 5}

And for functions of one or more arguments, provided they end on a IO-action:

>>> advise (printArgs stdout "foo1") foo1 False
foo1: False

Sum {getSum = 5}
>>> advise (printArgs stdout "foo2") foo2 'd' False
foo2: 'd' False

Sum {getSum = 5}

Advices can also tweak the result value of functions:

>>> advise (returnMempty @Top) foo2 'd' False
Sum {getSum = 0}

And they can be combined using Advice's Monoid instance before being applied:

>>> advise (printArgs stdout "foo2" <> returnMempty) foo2 'd' False
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 :: Type -> Constraint) r Source #

A generic transformation of IO-effectful functions of return type r, provided the functions satisfy certain constraint ca on all of their arguments.

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 Dep.IOAdvice.Basic for examples.

Instances

Instances details
Monoid (Advice ca r) Source # 
Instance details

Defined in Dep.IOAdvice

Methods

mempty :: Advice ca r #

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

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

Semigroup (Advice ca r) Source #

Advices compose "sequentially" when tweaking the arguments, and "concentrically" when tweaking the final IO 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 Dep.IOAdvice

Methods

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

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

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

Creating Advice values

makeAdvice Source #

Arguments

:: forall ca r. (forall as. All ca as => NP I as -> IO (IO r -> IO r, NP I as))

The function that tweaks the arguments and the execution.

-> Advice ca r 

The most general way of constructing Advices.

An Advice is a function that transforms other functions in an arity-polymorphic way. It receives the arguments of the advised function packed into an n-ary product NP, performs some effects based on them, and returns a potentially modified version of the arguments, along with a function for tweaking the execution of the advised function.

>>> :{
 doesNothing :: forall ca r. Advice ca r
 doesNothing = makeAdvice (\args -> pure (id,  args)) 
:}

makeArgsAdvice Source #

Arguments

:: forall ca r. (forall as. All ca as => NP I as -> IO (NP I as))

The function that tweaks the arguments.

-> Advice ca r 

Create an advice which only tweaks and/or analyzes the function arguments.

>>> :{
 doesNothing :: forall ca r. Advice ca r
 doesNothing = makeArgsAdvice pure
:}

makeExecutionAdvice Source #

Arguments

:: forall ca r. (IO r -> IO r)

The function that tweaks the execution.

-> Advice ca r 

Create an advice which only tweaks the execution of the final monadic action.

>>> :{
 doesNothing :: forall ca r. Advice ca r
 doesNothing = makeExecutionAdvice id
:}

Applying Advices

advise Source #

Arguments

:: forall ca r as advisee. (Multicurryable as r advisee, All ca as) 
=> Advice ca 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 IO, and all of its arguments must satisfy the ca constraint.

>>> :{
 foo :: Int -> 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 -> IO String
 bar _ = pure "bar"
 advisedBar1 = advise (returnMempty @Top) bar
 advisedBar2 = advise @Top returnMempty bar
:}

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 r. Advice (Show `And` Eq `And` Ord) 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 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 r

Advice with less restrictive constraint on the args.

-> Advice more r

Advice with more restrictive constraint on the args.

Makes the constraint on the arguments more restrictive.

Advising and deceiving entire records

adviseRecord is a version of advise that, instead of working on bare functions, transforms entire records-of-functions in one go. It also works 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
    }
  env :: Env IO
  env =
    let logger = Logger \_ -> pure ()
        repository =
          Repository {select = \_ -> pure [], insert = \_ -> pure ()} &
          adviseRecord @Top @Top mempty 
        controller =
          Controller { serve = \_ -> pure "view" } &
          adviseRecord @Top @Top mempty 
     in Env {logger, repository, controller}
:}

adviseRecord Source #

Arguments

:: forall ca cr advised. AdvisedRecord ca cr advised 
=> (forall r. cr r => NonEmpty (TypeRep, String) -> Advice ca r)

The advice to apply.

-> advised IO

The record to advise recursively.

-> advised IO

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. The elements come innermost-first.

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.

"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 #

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 #

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 #

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) #

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 () #

(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 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 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 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 -> () #

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 #

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

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 #

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) #

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 #

Functor I 
Instance details

Defined in Data.SOP.BasicFunctors

Methods

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

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

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 #

NFData1 I

Since: sop-core-0.2.5.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

liftRnf :: (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 #

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 #

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 #

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 #

NFData a => NFData (I a)

Since: sop-core-0.2.5.0

Instance details

Defined in Data.SOP.BasicFunctors

Methods

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

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.2-8cmRYB37llUAjnR98I5kI0" '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 #