@@ -1154,8 +1154,24 @@ do e ← get_env,
1154
1154
since it is expensive to execute `get_mathlib_dir` many times. -/
1155
1155
meta def is_in_mathlib (n : name) : tactic bool :=
1156
1156
do ml ← get_mathlib_dir, e ← get_env, return $ e.is_prefix_of_file ml n
1157
+
1158
+ /-- auxiliary function for apply_under_pis -/
1159
+ private meta def apply_under_pis_aux (func arg : pexpr) : ℕ → expr → pexpr
1160
+ | n (expr.pi nm bi tp bd) := expr.pi nm bi (pexpr.of_expr tp) (apply_under_pis_aux (n+1 ) bd)
1161
+ | n _ :=
1162
+ let vars := ((list.range n).reverse.map (@expr.var ff)),
1163
+ bd := vars.foldl expr.app arg.mk_explicit in
1164
+ func bd
1165
+
1166
+ /--
1167
+ Assumes `pi_expr` is of the form `Π x1 ... xn, _`.
1168
+ Creates a pexpr of the form `Π x1 ... xn, func (arg x1 ... xn)`.
1169
+ All arguments (implicit and explicit) to `arg` should be supplied. -/
1170
+ meta def apply_under_pis (func arg : pexpr) (pi_expr : expr) : pexpr :=
1171
+ apply_under_pis_aux func arg 0 pi_expr
1172
+
1157
1173
/--
1158
- Tries to derive unary instances by unfolding the newly introduced type.
1174
+ Tries to derive instances by unfolding the newly introduced type and applying type class resolution .
1159
1175
1160
1176
For example,
1161
1177
```
@@ -1164,21 +1180,32 @@ For example,
1164
1180
adds an instance `ring new_int`, defined to be the instance of `ring ℤ` found by `apply_instance`.
1165
1181
1166
1182
Multiple instances can be added with `@[derive [ring, module ℝ]]`.
1183
+
1184
+ This derive handler applies only to declarations made using `def`, and will fail on such a
1185
+ declaration if it is unable to derive an instance. It is run with higher priority than the built-in
1186
+ handlers, which will fail on `def`s.
1167
1187
-/
1168
- @[derive_handler] meta def delta_instance : derive_handler :=
1169
- λ cls tp,
1170
- (do tp' ← mk_const tp,
1171
- tgt ← to_expr ``(%%cls %%tp'),
1172
- (_, v) ← solve_aux tgt (delta_target [tp] >> apply_instance >> done),
1173
- v ← instantiate_mvars v,
1174
- nm ← get_unused_name $ tp ++
1175
- match tgt with
1176
- | expr.app (expr.const nm _) _ := nm
1188
+ @[derive_handler, priority 2000 ] meta def delta_instance : derive_handler :=
1189
+ λ cls new_decl_name,
1190
+ do env ← get_env,
1191
+ if env.is_inductive new_decl_name then return ff else
1192
+ do new_decl_type ← declaration.type <$> get_decl new_decl_name,
1193
+ new_decl_pexpr ← resolve_name new_decl_name,
1194
+ tgt ← to_expr $ apply_under_pis cls new_decl_pexpr new_decl_type,
1195
+ (_, inst) ← solve_aux tgt
1196
+ (intros >> reset_instance_cache >> delta_target [new_decl_name] >> apply_instance >> done),
1197
+ inst ← instantiate_mvars inst,
1198
+ tgt ← instantiate_mvars tgt,
1199
+ nm ← get_unused_decl_name $ new_decl_name ++
1200
+ match cls with
1201
+ -- the postfix is needed because we can't protect this name. using nm.last directly can
1202
+ -- conflict with open namespaces
1203
+ | (expr.const nm _) := (nm.last ++ " _1" : string)
1177
1204
| _ := " inst"
1178
1205
end ,
1179
- add_decl $ mk_definition nm [] tgt v ,
1206
+ add_decl $ mk_definition nm inst.collect_univ_params tgt inst ,
1180
1207
set_basic_attribute `instance nm tt,
1181
- return tt) <|> return ff
1208
+ return tt
1182
1209
1183
1210
/-- `find_private_decl n none` finds a private declaration named `n` in any of the imported files.
1184
1211
@@ -1207,9 +1234,9 @@ do env ← get_env,
1207
1234
1208
1235
open lean.parser interactive
1209
1236
1210
- /-- `import_private foo from bar` finds a private declaration `foo` in the same file as `bar`
1211
- and creates a local notation to refer to it.
1212
-
1237
+ /-- `import_private foo from bar` finds a private declaration `foo` in the same file as `bar`
1238
+ and creates a local notation to refer to it.
1239
+
1213
1240
`import_private foo`, looks for `foo` in all imported files. -/
1214
1241
@[user_command]
1215
1242
meta def import_private_cmd (_ : parse $ tk " import_private" ) : lean.parser unit :=
0 commit comments