Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
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 #
NatToPeano 0 = 'Z | |
NatToPeano n = 'S (NatToPeano (n - 1)) |
type family PeanoToNat n where ... Source #
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 |