
Some notes on inductive families
--------------------------------

** Syntax

The syntax for patterns which are instantiated by type checking (instantiated
or dot patterns) is ".p". For instance,

    subst .x x refl px = px

or

    map .zero	 f []	     = []
    map .(suc n) f (x :: xs) = f x :: map n f xs

In the second example there's some subtle things. The n looks as though it's
bound in the dot pattern. This is impossible since the dot patterns will be
thrown away after type checking. What should happen is that the hidden argument
to _::_ gets the name n and that's where the binding happens.

This poses a problem for scope checking. The dot pattern can be an arbitrary
term, but it might contain unbound variables. The scope checker will have to
bind unbound variables. Maybe that's not a problem?

The problem is: how to implement scope checking without copy-pasting between the
ToAbstract instance and the BindToAbstract instance for expressions?
Generalising a bit does the trick.

Come to think of it, binding variables in dot patterns is a bad idea. It makes
the type checking much harder: how to type check a dot pattern (in which
context). So the cons case above will have to be one of these two:

  map .(suc _) f (x :: xs)	 = f x :: map _ f xs
  map .(suc n) f (_::_ {n} x xs) = f x :: map n f xs

** Type checking

Step 0: Type checking the datatype

  Nothing strange. We just lift some of the previous restrictions on datatypes.

Step 1: Type checking the pattern

  Two interesting differences from the ordinary type checking:

    addFirstOrderMeta (α : A)
    ─────────────────────────	same for dot patterns
     Γ ⊢ _ : A --> Γ ⊢ α, α


    c : Δ -> Θ -> D xs ss'   Γ ⊢ ps : Θ[ts] --> Γ' ⊢ us, αs   Γ' ⊢ ss = us : Θ[ts]
    ──────────────────────────────────────────────────────────────────────────────
		      Γ ⊢ c ps : D ts ss --> Γ' ⊢ c ts us, αs

  Interaction between first order metas and η-expansion?
  Suppose

    data D : (N -> N) -> Set where
      id : D (\x -> x)

    h : (f : N -> N) -> D f -> ..
    h _ id

  Now we have to check α = \x -> x : N -> N which will trigger η-expansion and
  we'll end up with α x = x : N which we can't solve.

  We'll ignore this for now. Possible solution could be to distinguish between
  variables introduced by η-expansion and variables bound in the pattern.

Step 2: Turn unsolved metas into bound variables

  - make sure that there are no unsolved constraints from type checking the
    patterns (if so, fail)

  - we need to remember where the first order metas come from, or at least the
    order in which they are generated, so type checking should produce a list of
    first order metas

  - how to get the context in the right order? explicit variables have been
    added to the context but not implicit ones. we should probably make sure
    that the final context is the right one (otherwise reduction will not work
    properly).

  - example:

      f y _ (cons _ x xs)

    the context after type checking is (y x : A)(xs : List A) with meta
    variables (α β : N), where α := suc β. We'd want the final pattern to be

      f y .(suc n) (cons n x xs)

    and the context in the right hand side (y : A)(n : N)(x : A)(xs : List A).

    Solution:

    - pull out the context (y x : A)(xs : List A) and the meta context
      (α := suc β : N)(β : N) and traverse the pattern again, building the right
      context, instantiating uninstantiated metas to fresh variables.

    Quick solution:

    - re-type check the pattern when we know which patterns are dotted and which
      are variables. This also gets rid of (some of) the tricky deBruijn
      juggling that comes with the first-order metas.

    - Problem: when we say

	subst ._ _ refl

      could this mean

	subst x .x refl ?

      Answer: no, an explicit underscore can never become dotted. But there is a
      similar problem in

	tail ._ (x :: xs)

      Here we might instantiate the hidden length in the _::_ rather than the
      dotted first argument. So we need to keep track of first-order metas that
      'wants' to be instantiated, and instantiate those at higher priority than
      others.

      Why is this a problem? The user won't be able to tell (at least not easily)
      that she got

	tail n (_::_ .{n} x xs)

      rather than

	tail .n (_::_ {n} x xs)

      The problem is rather an implementation problem. We want to check that
      dotted patterns actually get instantiated, and give an error otherwise.
      How would we distinguish this case from the bad cases?

Step 3: Type check dot patterns and compare to the inferred values

  * after step 2 the context will be the correct one.

  * where do we find the type to check against? look at the meta variables
    generated during type checking

  So,

  - traverse the pattern with the list of meta-variables

  - for each dot pattern,
    + look up the type of the corresponding meta
    + and check that it's equal to the meta-variable


A BETTER SOLUTION
─────────────────

Context splitting a la Thierry.

For each clause, generate a case tree. Each case is an operation on the context:

(case x of C ys : D ss -> t) corresponds to

(Δ₁, x : D ts, Δ₂) ─→ (Δ₁, ys : Γ, Δ₂[C ys/x])σ
  where σ = unify(ss, ts)

So to type check a clause:

  ∙ generate case tree

  ∙ perform the context splitting (remembering the substitutions σ)

  ∙ verify that σ corresponds exactly to the dotted patterns

Questions:

  ∙ what is the unification algorithm?

  ∙ what argument to split on?

    ∙ first constructor pattern? Consider:

      data D : Set -> Set where
	nat  : D Nat
	bool : D Bool

      f : (A : Set) -> A -> D A -> X
      f .Nat zero nat = x

      Here we can't split on zero first, since the type is A.

    ∙ first constructor pattern whose type is a datatype

      error if there are constructor patterns left but no argument can be split

 vim: tw=80 sts=2 sw=2 fo=tcq

