123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- ------------------------------------------------------------------------
- Notes after class discussion 2007-08-17 (Ulf, NAD)
- These are just some quick and dirty notes outlining the outcome of the
- discussion. The use cases motivating the choices done are not
- discussed.
- Class declarations:
- record class C Γ : Δ where
- ...
- data class C Γ : Δ where
- ...
- No restrictions on parameters or indices.
- Instance declarations:
- f : ...
- f = ...
- instance f
- or perhaps
- instance f : ...
- f = ...
- f and the instance declaration have to be in the same scope.
- The instance which f declares is not in scope (with respect to
- instance search, see below) in the type signature of f, but it is in
- scope in the body of f (perhaps).
- The type of f has to evaluate to the normal form Γ -> C Δ, where C
- is a class. Γ has to consist solely of:
- • variables which are "rigid" in Δ (arguments to type constructors),
- and/or
- • class type constructors applied to arbitrary arguments. Denote
- these by C' Δ'.
- The type of f gives rise to a rewrite rule:
- C Δ -> C' Δ' (With an empty RHS if C' Δ' is empty.)
- The collection of all instance rewrite rules always has to be
- terminating. For every new instance added the termination checker is
- run on the rewrite rules (treating data/record type constructors in
- Δ/Δ' as constructors). One could also imagine a more local variant,
- in which the "recursive calls" in the RHS always have to be strictly
- structurally smaller than the LHS arguments.
- We may also allow higher-order types, in which case the RHSs become
- higher-order and the positive occurrences in C' Δ' should be
- inspected by the termination checker.
- Superclass declarations:
- record class C₁ Γ : Δ -> Setⁿ where
- ...
- instance x : C₂ X
- ...
- C₂ has to be a class; C₂ X becomes a superclass of C₁ Γ Δ.
- Searching for instances:
- If ? : C Γ, where C is a class, then ordinary unification is not
- used. Instead a special instance search is performed.
- The instance search is performed in several "levels". First a match
- for C Γ is searched for. If several matches are found, an error is
- emitted (ambiguous instances). If exactly one match is found, that
- match is bound to the meta variable. And if no matches are found,
- the search continues with the superclasses of C Γ, in a
- breadth-first manner. (First all immediate superclasses, all at the
- same time. Then the next level, and so on.)
- The search at a specific level is done in the following way:
- ⑴ All instances in scope are collected. Locally bound arguments
- whose types are of the form outlined for instances above also
- count as instances.
- ⑵ The rewrite rules generated by the instances are applied to the
- goals at hand (for instance C Γ), yielding new goals. This is
- repeated until no rules apply any more. Due to the termination
- checking done we know that this will terminate (right?).
- ⑶ All successful matches (search trees whose leaves all correspond
- to empty RHSs) are collected.
- From a successful match a dictionary can be built by applying the
- instance functions in a way corresponding to the resulting search
- tree; all arguments to these functions are either given by the goal
- at hand (the rigid variables) or by the children in the search tree.
- ------------------------------------------------------------------------
- A class system
- --------------
- what can be a class?
- - any datatype/record
- what is an instance?
- - an element of a class (possibly parameterised)
- - parameterised by what?
- + other instances clearly
- + non-instances? yes, arguments to the classes
- some examples:
- class Eq (A : Set) : Set where
- eq : (_==_ : A -> A -> Bool) -> Eq A
- instance
- eqList : {A : Set} -> Eq A -> Eq (List A)
- eqList eqA = ..
- what are the restrictions on an instance declaration?
- - should probably be
- instance i : Δ -> Cs -> C ts
- where
- Cs are classes
- Δ can be inferred from C ts
- - instance search will proceed as follows:
- + given a goal C ss, unify with C ts to get ρ (deciding all of Δ)
- + the new goals are Cs ρ
- multiparameter type classes?
- - how difficult?
- - necessary? clearly useful (at least with inductive families)
- functional dependecies
- - probably not needed (we have associated types for free)
- zero parameter type classes are useful:
- class True : Set where
- instance tt : True
- A constructor can be declared an instance by writing instance before the
- name. The normal checks are applied to the type.
- _/_ : (n m : Nat) -> {m ≠ 0} -> Nat
- m / n = ..
- now x / 3 requires a proof of 3 ≠ 0 = True for which there is an instance
- (tt). This would work with an inductive definition of ≠ as well (but requires
- multiparameter classes):
- class _≠_ : Nat -> Nat -> Set where
- instance neqZS : {m : Nat} -> 0 ≠ suc m
- instance neqSZ : {n : Nat} -> suc n ≠ 0
- instance neqSS : {n m : Nat} -> n ≠ m -> suc n ≠ suc m
- How to do super classes?
- class Ord (A : Set){eqA : Eq A} : Set where
- ord : (compare : A -> A -> Ordering) -> Ord A {eqA}
- instance ordNat : Ord Nat
- ordNat = ord compareNat
- this doesn't really work...
- sort : {A : Set} -> {Ord A} -> List A -> List A
- there is no instance Eq A here. Ord A must contain Eq A
- class Ord (A : Set) : Set where
- ord : {Eq A} -> (compare : A -> A -> Ordering) -> Ord A
- how to get the Eq dictionary from the Ord dictionary (nothing recording the
- relationship here). One attempt:
- instance ordToEq : {A : Set} -> Ord A -> Eq A
- ordToEq (ord eq _) = eq
- How does this work with other instances (clearly overlapping)? Maybe there is
- a good reason it's treated specially in Haskell... It would be nice not to
- have to introduce more syntax.
- Finding instances
- -----------------
- Instances form a rewriting system (there is a paper about this stuff...)
- instance i : Δ -> Cs -> C ts
- corresponds to a rule
- ∀ Δ. C ts --> Cs
- vim: sts=2 sw=2 tw=80
|