| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Data.Arity.Linear
Description
Synopsis
- data Peano
- type family NatToPeano n where ...
- type family PeanoToNat n where ...
- type family FunN n a b where ...
- type family Arity b f where ...
- class IsFunN a b f
Documentation
type family NatToPeano n where ... Source #
Equations
| NatToPeano 0 = 'Z | |
| NatToPeano n = 'S (NatToPeano (n - 1)) |
type family PeanoToNat n where ... Source #
Equations
| PeanoToNat 'Z = 0 | |
| PeanoToNat ('S n) = 1 + PeanoToNat n |
type family FunN n a b where ... Source #
represents a function taking FunN n a bn linear arguments of
type a and returning a result of type b.
type family Arity b f where ... Source #
The Arity type family exists to help the type checker fill in
blanks. Chances are that you can safely ignore Arity completely if it's in
the type of a function you care. But read on if you are curious.
The idea is that in a function like elim some of the
type arguments are redundant. The function has an ambiguous type, so you will
always have to help the compiler either with a type annotation or a type
application. But there are several complete ways to do so. In
elim, if you give the values of n, a, and b,
then you can deduce the value of f (indeed, it's ). With
FunN n a bArity we can go in the other direction: if b and f are both known, then
we know that n is Arity b f
Arity returns a Nat rather than a Peano because the result is never
consumed. It exists to infer arguments to functions such as
elim from the other arguments if they are known.
Arity could theorically be an associated type family to the IsFunN type
class. But it's better to make it a closed type family (which can't be
associated to a type class) because it lets us give a well-defined error
case. In addition, GHC cannot see that 0 /= 1 + (? :: Nat) and as a result we get
some overlap which is only allowed in (ordered) closed type families.
The IsFun type class is meant to help the type checker fill in
blanks. Chances are that you can safely ignore IsFun completely if it's in
the type of a function you care. But read on if you are curious.
The type class IsFun is a kind of inverse to FunN, it is meant to be
read as if and only if there exists IsFunN a b fn such that f =
(FunN n a bn can be retrieved as or
Arity b f).ArityV f
The reason why Arity (read its documentation first) is not sufficient for
our purpose, is that it can find n if f is a linear function of the
appropriate shape. But what if f is partially undetermined? Then it is
likely that Arity will be stuck. But we know, for instance, that if f = a1
%1 -> a2 %1 -> c then we must have a1 ~ a2. The trick is that instance
resolution of IsFun will add unification constraints that the type checker
has to solve. Look in particular at the instance : it matches liberally, so triggers on quite underdetermined IsFunN a b (a' %p ->
f))f, but has
equality constraints in its context which will help the type checker.
Instances
| IsFunN a b b Source # | |
Defined in Data.Arity.Linear.Internal | |
| (IsFunN a b f, a' ~ a, p ~ 'One) => IsFunN a b (a' %p -> f) Source # | |
Defined in Data.Arity.Linear.Internal | |