Safe Haskell | None |
---|---|
Language | Haskell2010 |
The HList library
(C) 2004, Oleg Kiselyov, Ralf Laemmel, Keean Schupke
Some very basic technology for faking dependent types in Haskell.
- class Apply f a where
- class ApplyAB f a b where
- data Fun (cxt :: k1) (getb :: k2) = Fun (forall a. FunCxt cxt a => a -> FunApp getb a)
- data Fun' (cxt :: k1) (geta :: k2) = Fun' (forall b. FunCxt cxt b => FunApp geta b -> b)
- type family FunApp (fns :: k) a
- type family FunCxt (cxts :: k) a :: Constraint
- data HPrint = HPrint
- data HRead = HRead
- data HShow = HShow
- data HComp g f = HComp g f
- data Comp = Comp
- newtype HSeq x = HSeq x
- data HFlip = HFlip
- newtype HFmap f = HFmap f
- newtype LiftA2 f = LiftA2 f
- data HUntag = HUntag
- data Label l = Label
- labelToProxy :: Label l -> Proxy l
- class ShowLabel l where
- hTrue :: Proxy True
- hFalse :: Proxy False
- type family HAnd (t1 :: Bool) (t2 :: Bool) :: Bool
- hAnd :: Proxy t1 -> Proxy t2 -> Proxy (HAnd t1 t2)
- type family HOr (t1 :: Bool) (t2 :: Bool) :: Bool
- hOr :: Proxy t1 -> Proxy t2 -> Proxy (HOr t1 t2)
- type family HNot (x :: Bool) :: Bool
- class HNotFD (b :: Bool) (nb :: Bool) | b -> nb, nb -> b
- hNot :: HNotFD a notA => Proxy a -> Proxy notA
- class HCond (t :: Bool) x y z | t x y -> z where
- type family HBoolEQ (t1 :: Bool) (t2 :: Bool) :: Bool
- data HNat
- hZero :: Proxy HZero
- hSucc :: Proxy (n :: HNat) -> Proxy (HSucc n)
- hPred :: Proxy (HSucc n) -> Proxy n
- class HNat2Integral (n :: HNat) where
- type family HNat2Nat (n :: HNat) :: Nat
- class HNats2Integrals (ns :: [HNat]) where
- type family HNatEq (t1 :: HNat) (t2 :: HNat) :: Bool
- type family HLt (x :: HNat) (y :: HNat) :: Bool
- hLt :: Proxy x -> Proxy y -> Proxy (HLt x y)
- type family HLe (x :: HNat) (y :: HNat) :: Bool
- hLe :: Proxy x -> Proxy y -> Proxy (HLe x y)
- type family HDiv2 (x :: HNat) :: HNat
- data HNothing = HNothing
- newtype HJust x = HJust x
- class HEq (x :: k) (y :: k) (b :: Bool) | x y -> b
- type HEqK (x :: k1) (y :: k2) (b :: Bool) = HEq (Proxy x) (Proxy y) b
- hEq :: HEq x y b => x -> y -> Proxy b
- class HEqByFn f => HEqBy (f :: t) (x :: k) (y :: k) (b :: Bool) | f x y -> b
- class HEqByFn f
- type Arity f n = (ArityFwd f n, ArityRev f n)
- class ArityFwd (f :: *) (n :: HNat) | f -> n
- class ArityRev (f :: *) (n :: HNat)
- class HCast x y where
- class HCast1 (b :: Bool) x y where
- class Fail (x :: k)
- type ErrText x = Text x
- type ErrShowType x = ShowType x
- type FieldNotFound key collection = (ErrText "key" :<>: ErrShowType key) :$$: (ErrText "could not be found in" :<>: ErrShowType collection)
- type ExcessFieldFound key collection = (ErrText "found field" :<>: ErrShowType key) :$$: (ErrText "when it should be absent from" :<>: ErrShowType collection)
- type HNatIndexTooLarge (nat :: HNat) (r :: [k] -> *) (xs :: [k]) = ((ErrText "0-based index" :<>: ErrShowType (HNat2Nat nat)) :<>: ErrText "is too large for collection") :$$: ErrShowType (r xs)
- type ExtraField x = ErrText "extra field" :<>: ErrShowType x
- type TypeablePolyK (a :: k) = Typeable a
- class SameLength' (es1 :: [k]) (es2 :: [m])
- class (SameLength' x y, SameLength' y x) => SameLength (x :: [k]) (y :: [m]) where
- asLengthOf :: SameLength x y => r x -> s y -> r x
- type family SameLengths (xs :: [[k]]) :: Constraint
- class SameLabels (x :: k) (y :: m)
- sameLabels :: SameLabels x y => p (r x) (f (q y)) -> p (r x) (f (q y))
- class HAllTaggedLV (ps :: [*])
- type family ZipTagged (ts :: [k]) (vs :: [*]) :: [*]
- module Data.Proxy
- module Data.Tagged
- class Monoid a where
- type family Any k0 :: k0 where ...
A heterogeneous apply operator
class Apply f a where Source #
simpler/weaker version where type information only propagates forward
with this one. applyAB
defined below, is more complicated / verbose to define,
but it offers better type inference. Most uses have been converted to
applyAB
, so there is not much that can be done with Apply
.
HLookupByHNat n l => Apply (FHLookupByHNat l) (Proxy HNat n) Source # | |
Apply (FHUProj sel ns) (HList l, Proxy HNat (HSucc n)) => Apply (Proxy Bool False, FHUProj sel ns) (HList ((:) * e l), Proxy HNat n) Source # | |
Apply (Proxy Bool True, FHUProj sel ns) (HList ((:) * e l), Proxy HNat n) Source # | |
((~) * ch (Proxy Bool (HBoolEQ sel (KMember n ns))), Apply (ch, FHUProj sel ns) (HList ((:) * e l), Proxy HNat n)) => Apply (FHUProj sel ns) (HList ((:) * e l), Proxy HNat n) Source # | |
Apply (FHUProj sel ns) (HList ([] *), n) Source # | |
Polymorphic functions are not first-class in haskell. An example of this is:
f op = (op (1 :: Double), op (1 :: Int))
RankNTypes
One solution is to enable `-XRankNTypes` and then write a type signature which might be `f :: (forall a. Num a => a -> a)`. This does not work in the context of HList, since we want to use functions that do not necessarily fall into the pattern of (forall a. c a => a -> a).
MultipleArguments
Another solution is to rewrite op
to look like
f op1 op2 = (op1 (1:: Double), op2 (1 :: Int))
In some sense this approach works (see HZip), but the result
is constrained to as many function applications as you are willing to
write (ex. a function that works for records of six entries would
look like hBuild f f f f f f
).
Defunctionalization
Therefore the selected solution is to write an instance of ApplyAB
for a data
type that takes the place of the original function. In other words,
data Fn = Fn instance ApplyAB Fn a b where applyAB Fn a = actual_fn a
Normally you would have been able to pass around the definition actual_fn.
Type inference / Local functional dependencies
Note that class ApplyAB
has three parameters and no functional dependencies.
Instances should be written in the style:
instance (int ~ Int, double ~ Double) => ApplyAB Fn int double where applyAB _ = fromIntegral
rather than the more natural
instance ApplyAB Fn Int Double
The first instance allows types to be inferred as if we had
class ApplyAB a b c | a -> b c
, while the second instance
only matches if ghc already knows that it needs
ApplyAB Fn Int Double
. Since applyAB Fn :: Int -> Double
has a monomorphic type, this trimmed down example does not
really make sense because applyAB (fromIntegral :: Int -> Double)
is exactly the same. Nontheless, the other uses of ApplyAB
follow this pattern, and the benefits are seen when the type of
applyAB Fn
has at least one type variable.
Additional explanation can be found in local functional dependencies
AmbiguousTypes
Note that ghc only allows AllowAmbiguousTypes when a type signature is provided. Thus expressions such as:
data AddJust = AddJust instance (y ~ Maybe x) => ApplyAB AddJust x y where applyAB _ x = Just x twoJustsBad = hMap AddJust . hMap AddJust -- ambiguous type
Are not accepted without a type signature that references the intermediate "b":
twoJusts :: forall r a b c. (HMapCxt r AddJust a b, HMapCxt r AddJust b c) => r a -> r c twoJusts a = hMap AddJust (hMap AddJust a :: r b)
An apply class with functional dependencies
class ApplyAB' f a b | f a -> b, f b -> a
Or with equivalent type families
class (GetB f a ~ b, GetA f b ~ a) => ApplyAB' f a b
would not require an annotation for twoJusts
. However,
not all instances of ApplyAB will satisfy those functional
dependencies, and thus the number of classes would proliferate.
Furthermore, inference does not have to be in one direction
only, as the example of HMap
shows.
class ApplyAB f a b where Source #
No constraints on result and argument types
(~) * (Tagged k t x) tx => ApplyAB HUntag tx x Source # | |
((~) * f1 (a -> b -> c), (~) * f2 (b -> a -> c)) => ApplyAB HFlip f1 f2 Source # | |
((~) * y y', (~) * fg (x -> y, y' -> z), (~) * r (x -> z)) => ApplyAB Comp fg r Source # | |
((~) * String string, Show a) => ApplyAB HShow a string Source # | |
((~) * String string, Read a) => ApplyAB HRead string a Source # | |
((~) * io (IO ()), Show x) => ApplyAB HPrint x io Source # | |
((~) * aa (a, a), Semigroup a) => ApplyAB UncurrySappend aa a Source # | |
((~) * aa (a, a), Monoid a) => ApplyAB UncurryMappend aa a Source # | |
((~) * x (Proxy * y), Monoid y) => ApplyAB ConstMempty x y Source # | |
(~) * hJustA (HJust a) => ApplyAB HFromJust hJustA a Source # | |
((~) * x (e, HList l), (~) * y (HList ((:) * e l))) => ApplyAB FHCons x y Source # | |
(~) * tx (Tagged k t x) => ApplyAB TaggedFn x tx Source # | |
((~) * x (Tagged k l v), (~) * y (HList ((:) * (Label k l) ((:) * v ([] *))))) => ApplyAB TaggedToKW x y Source # | |
(HZip3 a b c, (~) * x (HList a, HList b), (~) * y (HList c)) => ApplyAB HZipF x y Source # | |
((~) * x (Tagged k t (Maybe e), [Variant v]), (~) * y [Variant ((:) * (Tagged k t e) v)], MkVariant k t e ((:) * (Tagged k t e) v)) => ApplyAB HMaybiedToVariantFs x y Source # | |
(~) * y (Tagged k t (Maybe e)) => ApplyAB ConstTaggedNothing x y Source # | |
((~) * mx (Maybe x), (~) * my (Maybe y), HCast y x) => ApplyAB HCastF mx my Source # | |
((~) * ee (e, e), Eq e, (~) * bool Bool) => ApplyAB UncurryEq ee bool Source # | |
((~) * ux (RecordU x), (~) * hx (HList x), RecordUToRecord x) => ApplyAB BoxF ux hx Source # | |
((~) * hx (HList x), (~) * ux (RecordU x), RecordToRecordU x) => ApplyAB UnboxF hx ux Source # | |
(~) * e' e => ApplyAB HRmTag (e, t) e' Source # | |
((~) * y (ReadP x), Read x) => ApplyAB ReadElement (Proxy * x) y Source # | |
(Read v, ShowLabel k l, (~) * x (Tagged k l v), (~) * (ReadP x) y) => ApplyAB ReadComponent (Proxy * x) y Source # | |
(~) * hJustA (HJust a) => ApplyAB (HJust t) a hJustA Source # |
|
(ApplyAB f (x, y) z, (~) * mz (m z), (~) * mxy (m x, m y), Applicative m) => ApplyAB (LiftA2 f) mxy mz Source # | |
((~) * x (t a), (~) * y (t b), Functor t, ApplyAB f a b) => ApplyAB (HFmap f) x y Source # | |
(Monad m, ApplyAB f x fx, (~) * fx (m ()), (~) * pair (x, m ()), ApplyAB f x (m ())) => ApplyAB (HSeq f) pair fx Source # | |
((~) * hxs (HList xs), (~) * hxxs (HList ((:) * x xs))) => ApplyAB (FHCons2 x) hxs hxxs Source # | |
(~) * et (e, t) => ApplyAB (HAddTag t) e et Source # | |
((~) * l [e'], ApplyAB f e e', (~) * el (e, l)) => ApplyAB (Mapcar f) el l Source # | |
(HMapCxt HList f a b, (~) * as (HList a), (~) * bs (HList b)) => ApplyAB (HMapL f) as bs Source # | |
(HMapCxt r f a b, (~) * as (r a), (~) * bs (r b)) => ApplyAB (HMap f) as bs Source # | |
(HMapCxt Record f x y, (~) * rx (Record x), (~) * ry (Record y)) => ApplyAB (HMapR f) rx ry Source # | |
((~) * vx (Variant x), (~) * vy (Variant y), HMapAux Variant (HFmap f) x y, SameLength * * x y) => ApplyAB (HMapV f) vx vy Source # | apply a function to all values that could be in the variant. |
(Data b, (~) * x (t, c (b -> r)), (~) * y (c r)) => ApplyAB (GunfoldK c) x y Source # | |
(Data d, (~) * (c (d -> b), d) x, (~) * (c b) y) => ApplyAB (GfoldlK c) x y Source # | |
ApplyAB f e e' => ApplyAB (MapCar f) (e, HList l) (HList ((:) * e' l)) Source # | |
((~) * x' x, (~) * y' y) => ApplyAB (x' -> y') x y Source # | note this function will only be available at a single type
(that is, |
(ApplyAB f a b, ApplyAB g b c) => ApplyAB (HComp g f) a c Source # | |
(FunCxt k1 cxt b, (~) * (FunApp k2 geta b) a) => ApplyAB (Fun' k1 k2 cxt geta) a b Source # | |
(FunCxt k1 cxt a, (~) * (FunApp k2 getb a) b) => ApplyAB (Fun k1 k2 cxt getb) a b Source # | |
Fun
can be used instead of writing a new instance of
ApplyAB
. Refer to the definition/source for the the most
concise explanation. A more wordy explanation is given below:
A type signature needs to be provided on Fun
to make it work.
Depending on the kind of the parameters to Fun
, a number of
different results happen.
ex1
A list of kind [* -> Constraint]
produces those
constraints on the argument type:
>>>
:set -XDataKinds
>>>
let plus1f x = if x < 5 then x+1 else 5
>>>
let plus1 = Fun plus1f :: Fun '[Num, Ord] '()
>>>
:t applyAB plus1
applyAB plus1 :: (Num b, Ord b) => b -> b
>>>
let xs = [1 .. 8]
>>>
map (applyAB plus1) xs == map plus1f xs
True
Also note the use of '()
to signal that the result
type is the same as the argument type.
A single constraint can also be supplied:
>>>
let succ1 = Fun succ :: Fun Enum '()
>>>
:t applyAB succ1
applyAB succ1 :: Enum b => b -> b
>>>
let just = Fun Just :: Fun '[] Maybe
>>>
:t applyAB just
applyAB just :: a -> Maybe a
data Fun' (cxt :: k1) (geta :: k2) Source #
see Fun
. The only difference here is that the argument
type is calculated from the result type.
>>>
let rd = Fun' read :: Fun' Read String
>>>
:t applyAB rd
applyAB rd :: Read b => [Char] -> b
>>>
let fromJust' = Fun' (\(Just a) -> a) :: Fun' '[] Maybe
>>>
:t applyAB fromJust'
applyAB fromJust' :: Maybe b -> b
Note this use of Fun' means we don't have to get the b out of Maybe b
,
type family FunCxt (cxts :: k) a :: Constraint Source #
Simple useful instances of Apply
print. An alternative implementation could be:
>>>
let hPrint = Fun print :: Fun Show (IO ())
This produces:
>>>
:t applyAB hPrint
applyAB hPrint :: Show a => a -> IO ()
read
>>>
applyAB HRead "5.0" :: Double
5.0
Compose two instances of ApplyAB
>>>
applyAB (HComp HRead HShow) (5::Double) :: Double
5.0
HComp g f | g . f |
app Comp (f,g) = g . f
. Works like:
>>>
applyAB Comp (succ, pred) 'a'
'a'
>>>
applyAB Comp (toEnum :: Int -> Char, fromEnum) 10
10
Note that defaulting will sometimes give you the wrong thing
used to work (with associated types calculating result/argument types) >>> applyAB Comp (fromEnum, toEnum) 'a' *** Exception: Prelude.Enum.().toEnum: bad argument
((a,b) -> f a >> b)
HSeq x |
HFmap f |
LiftA2 f |
Proxy
see Data.Proxy
A special Proxy
for record labels, polykinded
(HasField k l (Record r) u, HasFieldPath needJust ls u v) => HasFieldPath needJust ((:) * (Label k l) ls) (Record r) v Source # | |
(HasField k l (Variant r) (Maybe u), HasFieldPath True ls u (Maybe v)) => HasFieldPath needJust ((:) * (Label k l) ls) (Variant r) (Maybe v) Source # | |
(~) * (Label k t) (Label Symbol t') => SameLabels * Symbol (Label k t) t' Source # | |
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Label k x) (Label k y) b Source # | |
(~) * (Label k2 t) (Label k1 t') => SameLabels * * (Label k2 t) (Label k1 t') Source # | |
(~) * (Label k2 t) (Label k1 t') => SameLabels * * (Label k2 t) (Tagged k1 t' a) Source # | |
(~) * (Label k t) (Label * (Lbl ix ns n)) => SameLabels * * (Label k t) (Lbl ix ns n) Source # | |
((~) * lv (Tagged k l v), HUnzip (Proxy [*]) ls vs lvs) => HUnzip (Proxy [*]) ((:) * (Label k l) ls) ((:) * v vs) ((:) * lv lvs) Source # | |
Show desc => Show (Label * (Lbl x ns desc)) # | |
HExtend (Label * (Lbl n ns desc)) (Proxy [Symbol] ((:) Symbol x xs)) Source # | Mixing two label kinds means we have to include
|
HExtend (Label * (Lbl n ns desc)) (Proxy [*] ((:) * (Lbl n' ns' desc') xs)) Source # | If possible, Label is left off:
|
HExtend (Label k x) (Proxy [*] ([] *)) Source # | to keep types shorter, ghc-7.6 does not accept |
ToSym * (a b c) x => EnsureLabel (a b c) (Label Symbol x) Source # | get the Label out of a |
EnsureLabel (Proxy k x) (Label k x) Source # | |
EnsureLabel (Label k x) (Label k x) Source # | |
(Labelable k1 x r s t a b, (~) * j (p a (f b)), (~) * k2 (p (r s) (f (r t))), (~) LabeledOpticType ty (LabelableTy r), LabeledOpticP ty p, LabeledOpticF ty f, LabeledOpticTo k1 ty x ((->) LiftedRep LiftedRep), LabelablePath xs i j) => LabelablePath ((:) * (Label k1 x) xs) i k2 Source # | |
type UnLabel a proxy ((:) * (Label a x) xs) Source # | |
type ZipTagged * ((:) * (Label k t) ts) ((:) * v vs) Source # | |
type HExtendR (Label * (Lbl n ns desc)) (Proxy [*] ((:) * (Lbl n' ns' desc') xs)) Source # | |
type HExtendR (Label * (Lbl n ns desc)) (Proxy [Symbol] ((:) Symbol x xs)) Source # | |
type HExtendR (Label Nat y) (Proxy [Symbol] ((:) Symbol x xs)) Source # | |
type HExtendR (Label Nat y) (Proxy [*] ((:) * x xs)) Source # | |
type HExtendR (Label Nat y) (Proxy [Nat] ((:) Nat x xs)) Source # | |
type HExtendR (Label Symbol y) (Proxy [Nat] ((:) Nat x xs)) Source # | |
type HExtendR (Label Symbol y) (Proxy [*] ((:) * x xs)) Source # | |
type HExtendR (Label Symbol y) (Proxy [Symbol] ((:) Symbol x xs)) Source # | |
type HExtendR (Label k x) (Proxy [*] ([] *)) Source # | |
type LabelsOf ((:) * (Label k l) r) Source # | |
labelToProxy :: Label l -> Proxy l Source #
Booleans
GHC already lifts booleans, defined as
data Bool = True | False
to types: Bool becomes kind and True and False (also denoted by 'True and 'False) become nullary type constructors.
The above line is equivalent to
data HTrue data HFalse
class HBool x instance HBool HTrue instance HBool HFalse
Value-level proxies
Conjunction
Disjunction
Compare with the original code based on functional dependencies:
class (HBool t, HBool t', HBool t'') => HOr t t' t'' | t t' -> t'' where hOr :: t -> t' -> t''
instance HOr HFalse HFalse HFalse where hOr _ _ = hFalse
instance HOr HTrue HFalse HTrue where hOr _ _ = hTrue
instance HOr HFalse HTrue HTrue where hOr _ _ = hTrue
instance HOr HTrue HTrue HTrue where hOr _ _ = hTrue
class HNotFD (b :: Bool) (nb :: Bool) | b -> nb, nb -> b Source #
as compared with HNot
this version is injective
Boolean equivalence
Naturals
The data type to be lifted to the type level
class HNat2Integral (n :: HNat) where Source #
hNat2Integral :: Integral i => Proxy n -> i Source #
KnownNat (HNat2Nat n) => HNat2Integral n Source # | |
class HNats2Integrals (ns :: [HNat]) where Source #
hNats2Integrals :: Integral i => Proxy ns -> [i] Source #
HNats2Integrals ([] HNat) Source # | |
(HNats2Integrals ns, HNat2Integral n) => HNats2Integrals ((:) HNat n ns) Source # | |
type family HNatEq (t1 :: HNat) (t2 :: HNat) :: Bool Source #
Equality on natural numbers (eventually to be subsumed by the universal polykinded HEq)
Maybies
We cannot use lifted Maybe since the latter are not populated
HJust x |
(Apply p s, HUnfoldFD p (ApplyR p s) z) => HUnfoldFD p (HJust (e, s)) ((:) * e z) Source # | |
Show x => Show (HJust x) Source # | |
(~) * hJustA (HJust a) => ApplyAB (HJust t) a hJustA Source # |
|
FromHJust l => FromHJust ((:) * (HJust e) l) Source # | |
type HUnfoldR p (HJust (e, s)) Source # | |
type FromHJustR ((:) * (HJust e) l) Source # | |
Polykinded Equality for types
class HEq (x :: k) (y :: k) (b :: Bool) | x y -> b Source #
We have to use Functional dependencies for now, for the sake of the generic equality.
type HEqK (x :: k1) (y :: k2) (b :: Bool) = HEq (Proxy x) (Proxy y) b Source #
Equality for types that may have different kinds. This definition
allows operations on Record [Tagged "x" a, Tagged 2 b]
to work
as expected.
class HEqByFn f => HEqBy (f :: t) (x :: k) (y :: k) (b :: Bool) | f x y -> b Source #
this class generalizes HEq by allowing the choice of f
to allow
equating only part of x and y
(~) Bool ((<=?) x y) b => HEqBy * Nat HLeFn x y b Source # | only in ghc >= 7.7 |
(HEq Ordering (CmpSymbol x y) GT nb, (~) Bool (HNot nb) b) => HEqBy * Symbol HLeFn x y b Source # | only in ghc >= 7.7
|
(~) Bool (HLe x y) b => HEqBy * HNat HLeFn x y b Source # | |
HEqBy k2 k1 f y x b => HEqBy * k1 (HDown k2 f) x y b Source # | |
(HEqBy k2 k1 le y x b1, (~) Bool (HNot b1) b2) => HEqBy * k1 (HNeq k2 le) x y b2 Source # | |
((~) * txv (Tagged k2 x v), (~) * tyw (Tagged k1 y w), HEq * v w b) => HEqBy * * EqTagValue txv tyw b Source # | |
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Proxy k x) (Proxy k y) b Source # | |
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Label k x) (Label k y) b Source # | |
HEqBy * k HLeFn x y b => HEqBy * * HLeFn (Tagged k x v) (Tagged k y w) b Source # | |
(HEqBy * HNat HLeFn n m b, (~) * ns ns') => HEqBy * * HLeFn (Lbl n ns desc) (Lbl m ns' desc') b Source # | Data.HList.Label3 labels can only be compared if they belong to the same namespace. |
Every instance of this class should have an instance of HEqBy
Arity
class ArityFwd (f :: *) (n :: HNat) | f -> n Source #
calculate the number of arguments a function can take
class ArityRev (f :: *) (n :: HNat) Source #
given the number of arguments a function can take, make sure the function type actually matches
Staged equality
Type-safe cast -- no longer need. We use a a ~ b
Cast
Error messages
A class without instances for explicit failure.
Note that with ghc>=8.0, `x :: TypeError` which is formatted properly.
Otherwise x
is made of nested (left-associated) promoted tuples.
For example:
(x ~ '( '( '("the", Int), "is wrong") ) ) :: ((,) Symbol *, Symbol)
Therefore code that works across ghc-7.6 through ghc-8.0 needs to use ErrText, ErrShowType, :<>:, :$$: to construct the type x.
TypeError Constraint x => Fail ErrorMessage x Source # | |
type ErrText x = Text x Source #
use the alias ErrText to prevent conflicts with Data.Text
GHC.TypeLits.:<>: and GHC.TypeLits.:$$: are re-exported
type ErrShowType x = ShowType x Source #
Error messages used elsewhere
type FieldNotFound key collection = (ErrText "key" :<>: ErrShowType key) :$$: (ErrText "could not be found in" :<>: ErrShowType collection) Source #
type ExcessFieldFound key collection = (ErrText "found field" :<>: ErrShowType key) :$$: (ErrText "when it should be absent from" :<>: ErrShowType collection) Source #
type HNatIndexTooLarge (nat :: HNat) (r :: [k] -> *) (xs :: [k]) = ((ErrText "0-based index" :<>: ErrShowType (HNat2Nat nat)) :<>: ErrText "is too large for collection") :$$: ErrShowType (r xs) Source #
type ExtraField x = ErrText "extra field" :<>: ErrShowType x Source #
type TypeablePolyK (a :: k) = Typeable a Source #
Constraining Lists
Length
class SameLength' (es1 :: [k]) (es2 :: [m]) Source #
Ensure two lists have the same length. We do case analysis on the first one (hence the type must be known to the type checker). In contrast, the second list may be a type variable.
(~) [m] es2 ([] m) => SameLength' k m ([] k) es2 Source # | |
(SameLength' k m xs ys, (~) [m] es2 ((:) m y ys)) => SameLength' k m ((:) k x xs) es2 Source # | |
class (SameLength' x y, SameLength' y x) => SameLength (x :: [k]) (y :: [m]) where Source #
symmetrical version of SameLength'
. Written as a class instead of
type SameLength a b = (SameLength' a b, SameLength' b a)
since ghc expands type synonyms, but not classes (and it seems to have the same result)
sameLength :: (r x `p` f (q y)) -> r x `p` f (q y) Source #
SameLength x y => Equality (r x) (q y) (r x) (q y)
used like simple
, except it restricts
the type-level lists involved to have the same length,
without fixing the type of container or the elements
in the list.
(SameLength' k m x y, SameLength' m k y x) => SameLength k m x y Source # | |
asLengthOf :: SameLength x y => r x -> s y -> r x Source #
type family SameLengths (xs :: [[k]]) :: Constraint Source #
type SameLengths k ([] [k]) Source # | |
type SameLengths k ((:) [k] x ([] [k])) Source # | |
type SameLengths k ((:) [k] x ((:) [k] y ys)) Source # | |
Labels
class SameLabels (x :: k) (y :: m) Source #
SameLabels * m (Label Symbol t) s => SameLabels Symbol m t s Source # | |
(~) * (Label k t) (Label Symbol t') => SameLabels * Symbol (Label k t) t' Source # | |
SameLabels * m (Label k t) s => SameLabels * m (Tagged k t a) s Source # | |
SameLabels [k1] [k2] ([] k1) ([] k2) Source # | |
SameLabels [k] [a] ([] k) ((:) a x xs) Source # | |
(~) * (Label k2 t) (Label k1 t') => SameLabels * * (Label k2 t) (Label k1 t') Source # | |
(~) * (Label k2 t) (Label k1 t') => SameLabels * * (Label k2 t) (Tagged k1 t' a) Source # | |
(~) * (Label k t) (Label * (Lbl ix ns n)) => SameLabels * * (Label k t) (Lbl ix ns n) Source # | |
SameLabels [a] [k] ((:) a x xs) ([] k) Source # | |
(SameLabels a2 a1 x y, SameLabels [a2] [a1] xs ys) => SameLabels [a2] [a1] ((:) a2 x xs) ((:) a1 y ys) Source # | |
sameLabels :: SameLabels x y => p (r x) (f (q y)) -> p (r x) (f (q y)) Source #
sameLabels
constrains the type of an optic, such that the labels
(t
in Tagged t a
) are the same. x
or y
may have more elements
than the other, in which case the elements at the end
of the longer list do not have their labels constrained.
see also sameLength
A list has only Tagged values
class HAllTaggedLV (ps :: [*]) Source #
The Record
, Variant
, TIP
, TIC
type constructors only make
sense when they are applied to an instance of this class
HAllTaggedLV ([] *) Source # | |
(HAllTaggedLV xs, (~) * x (Tagged k t v)) => HAllTaggedLV ((:) * x xs) Source # | |
re-exports
module Data.Proxy
module Data.Tagged
The class of monoids (types with an associative binary operation that has an identity). Instances should satisfy the following laws:
mappend mempty x = x
mappend x mempty = x
mappend x (mappend y z) = mappend (mappend x y) z
mconcat =
foldr
mappend mempty
The method names refer to the monoid of lists under concatenation, but there are many other instances.
Some types can be viewed as a monoid in more than one way,
e.g. both addition and multiplication on numbers.
In such cases we often define newtype
s and make those instances
of Monoid
, e.g. Sum
and Product
.
Identity of mappend
An associative operation
Fold a list using the monoid.
For most types, the default definition for mconcat
will be
used, but the function is included in the class definition so
that an optimized version can be provided for specific types.
Monoid Ordering | Since: 2.1 |
Monoid () | Since: 2.1 |
Monoid All | Since: 2.1 |
Monoid Any | Since: 2.1 |
Monoid Doc | |
Monoid [a] | Since: 2.1 |
Monoid a => Monoid (Maybe a) | Lift a semigroup into Since: 2.1 |
Monoid a => Monoid (IO a) | Since: 4.9.0.0 |
(Ord a, Bounded a) => Monoid (Min a) | Since: 4.9.0.0 |
(Ord a, Bounded a) => Monoid (Max a) | Since: 4.9.0.0 |
Monoid m => Monoid (WrappedMonoid m) | Since: 4.9.0.0 |
Semigroup a => Monoid (Option a) | Since: 4.9.0.0 |
Monoid a => Monoid (Identity a) | |
Monoid a => Monoid (Dual a) | Since: 2.1 |
Monoid (Endo a) | Since: 2.1 |
Num a => Monoid (Sum a) | Since: 2.1 |
Num a => Monoid (Product a) | Since: 2.1 |
Monoid (First a) | Since: 2.1 |
Monoid (Last a) | Since: 2.1 |
Monoid (Seq a) | |
Monoid (Predicate a) | |
Monoid (Comparison a) | |
Monoid (Equivalence a) | |
Monoid (Doc a) | |
(HProxies a, HMapCxt HList ConstMempty (AddProxy [*] a) a, HZip HList a a aa, HMapCxt HList UncurryMappend aa a) => Monoid (HList a) # | Analogous to the Monoid instance for tuples
|
Monoid (HList r) => Monoid (Record r) # | |
(Monoid x, Monoid (Variant ((:) * a b))) => Monoid (Variant ((:) * (Tagged k t x) ((:) * a b))) # | |
(Unvariant ((:) * (Tagged k t x) ([] *)) x, Monoid x) => Monoid (Variant ((:) * (Tagged k t x) ([] *))) # | |
Monoid (HList a) => Monoid (TIP a) # | |
Monoid (Variant l) => Monoid (TIC l) # | |
Monoid b => Monoid (a -> b) | Since: 2.1 |
(Monoid a, Monoid b) => Monoid (a, b) | Since: 2.1 |
Monoid (Proxy k s) | Since: 4.7.0.0 |
Monoid a => Monoid (Op a b) | |
(Monoid a, Monoid b, Monoid c) => Monoid (a, b, c) | Since: 2.1 |
Alternative f => Monoid (Alt * f a) | Since: 4.8.0.0 |
ArrowPlus p => Monoid (Tambara p a b) | |
(Semigroup a, Monoid a) => Monoid (Tagged k s a) | |
(Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a, b, c, d) | Since: 2.1 |
(Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) => Monoid (a, b, c, d, e) | Since: 2.1 |