inductive-families 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. Some notes on inductive families
  2. --------------------------------
  3. ** Syntax
  4. The syntax for patterns which are instantiated by type checking (instantiated
  5. or dot patterns) is ".p". For instance,
  6. subst .x x refl px = px
  7. or
  8. map .zero f [] = []
  9. map .(suc n) f (x :: xs) = f x :: map n f xs
  10. In the second example there's some subtle things. The n looks as though it's
  11. bound in the dot pattern. This is impossible since the dot patterns will be
  12. thrown away after type checking. What should happen is that the hidden argument
  13. to _::_ gets the name n and that's where the binding happens.
  14. This poses a problem for scope checking. The dot pattern can be an arbitrary
  15. term, but it might contain unbound variables. The scope checker will have to
  16. bind unbound variables. Maybe that's not a problem?
  17. The problem is: how to implement scope checking without copy-pasting between the
  18. ToAbstract instance and the BindToAbstract instance for expressions?
  19. Generalising a bit does the trick.
  20. Come to think of it, binding variables in dot patterns is a bad idea. It makes
  21. the type checking much harder: how to type check a dot pattern (in which
  22. context). So the cons case above will have to be one of these two:
  23. map .(suc _) f (x :: xs) = f x :: map _ f xs
  24. map .(suc n) f (_::_ {n} x xs) = f x :: map n f xs
  25. ** Type checking
  26. Step 0: Type checking the datatype
  27. Nothing strange. We just lift some of the previous restrictions on datatypes.
  28. Step 1: Type checking the pattern
  29. Two interesting differences from the ordinary type checking:
  30. addFirstOrderMeta (α : A)
  31. ───────────────────────── same for dot patterns
  32. Γ ⊢ _ : A --> Γ ⊢ α, α
  33. c : Δ -> Θ -> D xs ss' Γ ⊢ ps : Θ[ts] --> Γ' ⊢ us, αs Γ' ⊢ ss = us : Θ[ts]
  34. ──────────────────────────────────────────────────────────────────────────────
  35. Γ ⊢ c ps : D ts ss --> Γ' ⊢ c ts us, αs
  36. Interaction between first order metas and η-expansion?
  37. Suppose
  38. data D : (N -> N) -> Set where
  39. id : D (\x -> x)
  40. h : (f : N -> N) -> D f -> ..
  41. h _ id
  42. Now we have to check α = \x -> x : N -> N which will trigger η-expansion and
  43. we'll end up with α x = x : N which we can't solve.
  44. We'll ignore this for now. Possible solution could be to distinguish between
  45. variables introduced by η-expansion and variables bound in the pattern.
  46. Step 2: Turn unsolved metas into bound variables
  47. - make sure that there are no unsolved constraints from type checking the
  48. patterns (if so, fail)
  49. - we need to remember where the first order metas come from, or at least the
  50. order in which they are generated, so type checking should produce a list of
  51. first order metas
  52. - how to get the context in the right order? explicit variables have been
  53. added to the context but not implicit ones. we should probably make sure
  54. that the final context is the right one (otherwise reduction will not work
  55. properly).
  56. - example:
  57. f y _ (cons _ x xs)
  58. the context after type checking is (y x : A)(xs : List A) with meta
  59. variables (α β : N), where α := suc β. We'd want the final pattern to be
  60. f y .(suc n) (cons n x xs)
  61. and the context in the right hand side (y : A)(n : N)(x : A)(xs : List A).
  62. Solution:
  63. - pull out the context (y x : A)(xs : List A) and the meta context
  64. (α := suc β : N)(β : N) and traverse the pattern again, building the right
  65. context, instantiating uninstantiated metas to fresh variables.
  66. Quick solution:
  67. - re-type check the pattern when we know which patterns are dotted and which
  68. are variables. This also gets rid of (some of) the tricky deBruijn
  69. juggling that comes with the first-order metas.
  70. - Problem: when we say
  71. subst ._ _ refl
  72. could this mean
  73. subst x .x refl ?
  74. Answer: no, an explicit underscore can never become dotted. But there is a
  75. similar problem in
  76. tail ._ (x :: xs)
  77. Here we might instantiate the hidden length in the _::_ rather than the
  78. dotted first argument. So we need to keep track of first-order metas that
  79. 'wants' to be instantiated, and instantiate those at higher priority than
  80. others.
  81. Why is this a problem? The user won't be able to tell (at least not easily)
  82. that she got
  83. tail n (_::_ .{n} x xs)
  84. rather than
  85. tail .n (_::_ {n} x xs)
  86. The problem is rather an implementation problem. We want to check that
  87. dotted patterns actually get instantiated, and give an error otherwise.
  88. How would we distinguish this case from the bad cases?
  89. Step 3: Type check dot patterns and compare to the inferred values
  90. * after step 2 the context will be the correct one.
  91. * where do we find the type to check against? look at the meta variables
  92. generated during type checking
  93. So,
  94. - traverse the pattern with the list of meta-variables
  95. - for each dot pattern,
  96. + look up the type of the corresponding meta
  97. + and check that it's equal to the meta-variable
  98. A BETTER SOLUTION
  99. ─────────────────
  100. Context splitting a la Thierry.
  101. For each clause, generate a case tree. Each case is an operation on the context:
  102. (case x of C ys : D ss -> t) corresponds to
  103. (Δ₁, x : D ts, Δ₂) ─→ (Δ₁, ys : Γ, Δ₂[C ys/x])σ
  104. where σ = unify(ss, ts)
  105. So to type check a clause:
  106. ∙ generate case tree
  107. ∙ perform the context splitting (remembering the substitutions σ)
  108. ∙ verify that σ corresponds exactly to the dotted patterns
  109. Questions:
  110. ∙ what is the unification algorithm?
  111. ∙ what argument to split on?
  112. ∙ first constructor pattern? Consider:
  113. data D : Set -> Set where
  114. nat : D Nat
  115. bool : D Bool
  116. f : (A : Set) -> A -> D A -> X
  117. f .Nat zero nat = x
  118. Here we can't split on zero first, since the type is A.
  119. ∙ first constructor pattern whose type is a datatype
  120. error if there are constructor patterns left but no argument can be split
  121. vim: tw=80 sts=2 sw=2 fo=tcq