Mercurial > cpdt > repo
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># *) |