More flexible handling of universes, for instance some form of universe polymorphism, would be nice. Use cases:
- Sometimes a data type is needed on several levels (both equality on the level of Set and Set1, for instance). Or a function (like composition) may be needed on several levels. These different uses may occur in the same program.
- Sometimes a data type is needed on several levels in the same expression. Example: A deep embedding of a monad, along with the join operation.
data Monad (a : Set) : Set1 where
return : a -> Monad a
_>>=_ : {b : Set} -> Monad b -> (b -> Monad a) -> Monad a
join : forall {a} -> Monad (Monad a) -> Monad a
join x = x >>= \y -> y
- The type signature of
joinis not well-typed, sinceMonad adoes not live inSet.
Comment (Wolfram): However, this example is artificial at least because monads should be endo-functors, i.e.,
Monad a shoud be “the same kind of thing” as a.
Response (NAD): The example does not seem artificial to me, I sometimes define "monads" in this way. See also Monads Need Not Be Endofunctors.
A suggestion for how to solve this problem:
- Add a typing rule "lift" such that if
x : Setn, thenx : Set(n + 1). - Add a limited form of universe polymorphism, (hopefully) in such a way that every complete program can be translated into ordinary Agda with the lift rule above. Preliminary sketch:
- Let us (tentatively) introduce a type for universe levels,
Level, along with the operation which takes a level to its successor. Then (some) universe polymorphic operations can be written explicitly. - However, the resulting system may be too strong, so we restrict it by only allowing a single outermost quantifier for every definition (i.e. higher-rank universe polymorphism is not allowed).
- Furthermore the user is not allowed to write out this quantifier manually. Instead we infer it. The Monad declaration above is generalised as follows:
data Monad {i : Level} (a : Set i) : Set (i + 1) where return : a -> Monad a _>>=_ : {b : Set i} -> Monad b -> (b -> Monad a) -> Monad aBasically all uses ofSetbecomeSet i,Set1becomesSet (i + 1), etc. - Uses of universe-polymorphic definitions result in certain constraints on the indices. It must be possible to solve these constraints using just the lift typing rule. There may be several possible solutions; we pick the one in which the indices are lowest. (Note: We do not claim that there is a principal solution.)
For instance, for the type signature of
joinwe first infer a generalised variant as above:forall {i} {a : Set i} -> Monad {?1} (Monad {?2} a) -> Monad {?3} a,Here we get some constraints,?1 ≥ ?2 + 1,?2 ≥ iand?3 ≥ i. Furthermore all question marks have to be solved (locally, before proceeding with type checking) with expressions of the formi + kfor constant natural numbersk. We get the "lowest" solution?1 = i + 1,?2 = i,?3 = i. Another example: For the body ofjoin {i} {a} xwe get the generalised right-hand side_>>=_ {i = ?1} {a = a} {b = Monad {i = ?2} a} x (\(y : Monad {i = ?3} a) -> y : Monad {i = ?4} a)with the constraints{x ≥ i | i ∈ ?1, ?2, ?3, ?4},?1 ≥ ?2 + 1. We get the "lowest" solution?1 = i + 1,?2 = ?3 = ?4 = i. (This is a bit simplified since in reality the structure ofbwould first have to be inferred through unification, etc.)
- Let us (tentatively) introduce a type for universe levels,
The system outlined above may perhaps not be strong enough, but at least it solves some problems, is quite simple, and provides a testbed which we can test the limitations of. We should not extend the language without first having well-motivated use cases.
Considering the join operation as more primitive than the bind operation from a category theoretical point of view, I wonder how some intended implementation of
data Monad {i : Level} (a : Set i) : Set (i + 1) where
return : a -> Monad a
_>>=_ : {b : Set i} -> Monad b -> (b -> Monad a) -> Monad a
might look like. All I can think of at the moment has the signature
data Monad {i : Level} (a : Set i) : Set (max i c) where
return : a -> Monad a
_>>=_ : {b : Set i} -> Monad b -> (b -> Monad a) -> Monad a
for some constant level c, where max denotes the join in the upper semilattice of universe levels.
Page last modified on December 27, 2009, at 04:10 pm
Powered by
PmWiki