comparison src/Subset.v @ 71:db967eff40d7

sumbool
author Adam Chlipala <adamc@hcoop.net>
date Fri, 03 Oct 2008 12:02:44 -0400
parents 1e3c49602384
children 839d159cac5d
comparison
equal deleted inserted replaced
70:1e3c49602384 71:db967eff40d7
265 match n return (n > 0 -> {m : nat | n = S m}) with 265 match n return (n > 0 -> {m : nat | n = S m}) with
266 | O => fun _ => ! 266 | O => fun _ => !
267 | S n' => fun _ => [n'] 267 | S n' => fun _ => [n']
268 end); crush. 268 end); crush.
269 Defined. 269 Defined.
270
271
272 (** * Decidable Proposition Types *)
273
274 (** There is another type in the standard library which captures the idea of program values that indicate which of two propositions is true. *)
275
276 Print sumbool.
277 (** [[
278
279 Inductive sumbool (A : Prop) (B : Prop) : Set :=
280 left : A -> {A} + {B} | right : B -> {A} + {B}
281 For left: Argument A is implicit
282 For right: Argument B is implicit
283 ]] *)
284
285 (** We can define some notations to make working with [sumbool] more convenient. *)
286
287 Notation "'Yes'" := (left _ _).
288 Notation "'No'" := (right _ _).
289 Notation "'Reduce' x" := (if x then Yes else No) (at level 50).
290
291 (** The [Reduce] notation is notable because it demonstrates how [if] is overloaded in Coq. The [if] form actually works when the test expression has any two-constructor inductive type. Moreover, in the [then] and [else] branches, the appropriate constructor arguments are bound. This is important when working with [sumbool]s, when we want to have the proof stored in the test expression available when proving the proof obligations generated in the appropriate branch.
292
293 Now we can write [eq_nat_dec], which compares two natural numbers, returning either a proof of their equality or a proof of their inequality. *)
294
295 Definition eq_nat_dec (n m : nat) : {n = m} + {n <> m}.
296 refine (fix f (n m : nat) {struct n} : {n = m} + {n <> m} :=
297 match n, m return {n = m} + {n <> m} with
298 | O, O => Yes
299 | S n', S m' => Reduce (f n' m')
300 | _, _ => No
301 end); congruence.
302 Defined.
303
304 (** Our definition extracts to reasonable OCaml code. *)
305
306 Extraction eq_nat_dec.
307
308 (** %\begin{verbatim}
309 (** val eq_nat_dec : nat -> nat -> sumbool **)
310
311 let rec eq_nat_dec n m =
312 match n with
313 | O -> (match m with
314 | O -> Left
315 | S n0 -> Right)
316 | S n' -> (match m with
317 | O -> Right
318 | S m' -> eq_nat_dec n' m')
319 \end{verbatim}%
320
321 #<pre>
322 (** val eq_nat_dec : nat -> nat -> sumbool **)
323
324 let rec eq_nat_dec n m =
325 match n with
326 | O -> (match m with
327 | O -> Left
328 | S n0 -> Right)
329 | S n' -> (match m with
330 | O -> Right
331 | S m' -> eq_nat_dec n' m')
332 </pre>#
333
334 Proving this kind of decidable equality result is so common that Coq comes with a tactic for automating it. *)
335
336 Definition eq_nat_dec' (n m : nat) : {n = m} + {n <> m}.
337 decide equality.
338 Defined.
339
340 (** Curious readers can verify that the [decide equality] version extracts to the same OCaml code as our more manual version does. That OCaml code had one undesirable property, which is that it uses %\texttt{%#<tt>#Left#</tt>#%}% and %\texttt{%#<tt>#Right#</tt>#%}% constructors instead of the boolean values built into OCaml. We can fix this, by using Coq's facility for mapping Coq inductive types to OCaml variant types. *)
341
342 Extract Inductive sumbool => "bool" ["true" "false"].
343 Extraction eq_nat_dec'.
344
345 (** %\begin{verbatim}
346 (** val eq_nat_dec' : nat -> nat -> bool **)
347
348 let rec eq_nat_dec' n m0 =
349 match n with
350 | O -> (match m0 with
351 | O -> true
352 | S n0 -> false)
353 | S n0 -> (match m0 with
354 | O -> false
355 | S n1 -> eq_nat_dec' n0 n1)
356 \end{verbatim}%
357
358 #<pre>
359 (** val eq_nat_dec' : nat -> nat -> bool **)
360
361 let rec eq_nat_dec' n m0 =
362 match n with
363 | O -> (match m0 with
364 | O -> true
365 | S n0 -> false)
366 | S n0 -> (match m0 with
367 | O -> false
368 | S n1 -> eq_nat_dec' n0 n1)
369 </pre># *)