Coq

Личный сайт Go-разработчика из Казани

The Coq system is a proof assistant. It is designed to build and verify mathematical proofs. The Coq system contains the functional programming language Gallina and is capable of proving properties about programs written in this language.

Coq is a dependently typed language. This means that the types of the language may depend on the values of variables. In this respect, it is similar to other related languages such as Agda, Idris, F*, Lean, and others. Via the Curry-Howard correspondence, programs, properties and proofs are formalized in the same language.

Coq is developed in OCaml and shares some syntactic and conceptual similarity with it. Coq is a language containing many fascinating but difficult topics. This tutorial will focus on the programming aspects of Coq, rather than the proving. It may be helpful, but not necessary to learn some OCaml first, especially if you are unfamiliar with functional programming. This tutorial is based upon its OCaml equivalent

The standard usage model of Coq is to write it with interactive tool assistance, which operates like a high powered REPL. Two common such editors are the CoqIDE and Proof General Emacs mode.

Inside Proof General Ctrl+C Ctrl+<Enter> will evaluate up to your cursor.

1(*** Comments ***) 2 3(* Comments are enclosed in (* and *). It's fine to nest comments. *) 4 5(* There are no single-line comments. *) 6 7(*** Variables and functions ***) 8 9(* The Coq proof assistant can be controlled and queried by a command 10 language called the vernacular. Vernacular keywords are capitalized and 11 the commands end with a period. Variable and function declarations are 12 formed with the Definition vernacular. *) 13 14Definition x := 10. 15 16(* Coq can sometimes infer the types of arguments, but it is common practice 17 to annotate with types. *) 18 19Definition inc_nat (x : nat) : nat := x + 1. 20 21(* There exists a large number of vernacular commands for querying 22 information. These can be very useful. *) 23 24Compute (1 + 1). (* 2 : nat *) (* Compute a result. *) 25 26Check tt. (* tt : unit *) (* Check the type of an expressions *) 27 28About plus. (* Prints information about an object *) 29 30(* Print information including the definition *) 31Print true. (* Inductive bool : Set := true : Bool | false : Bool *) 32 33Search nat. (* Returns a large list of nat related values *) 34Search "_ + _". (* You can also search on patterns *) 35Search (?a -> ?a -> bool). (* Patterns can have named parameters *) 36Search (?a * ?a). 37 38(* Locate tells you where notation is coming from. Very helpful when you 39 encounter new notation. *) 40 41Locate "+". 42 43(* Calling a function with insufficient number of arguments does not cause 44 an error, it produces a new function. *) 45Definition make_inc x y := x + y. (* make_inc is nat -> nat -> nat *) 46Definition inc_2 := make_inc 2. (* inc_2 is nat -> nat *) 47Compute inc_2 3. (* Evaluates to 5 *) 48 49 50(* Definitions can be chained with "let ... in" construct. This is roughly 51 the same to assigning values to multiple variables before using them in 52 expressions in imperative languages. *) 53 54Definition add_xy : nat := let x := 10 in 55 let y := 20 in 56 x + y. 57 58(* Pattern matching is somewhat similar to switch statement in imperative 59 languages, but offers a lot more expressive power. *) 60 61Definition is_zero (x : nat) := 62 match x with 63 | 0 => true 64 | _ => false (* The "_" pattern means "anything else". *) 65 end. 66 67(* You can define recursive function definition using the Fixpoint 68 vernacular.*) 69 70Fixpoint factorial n := match n with 71 | 0 => 1 72 | (S n') => n * factorial n' 73 end. 74 75(* Function application usually doesn't need parentheses around arguments *) 76Compute factorial 5. (* 120 : nat *) 77 78(* ...unless the argument is an expression. *) 79Compute factorial (5-1). (* 24 : nat *) 80 81(* You can define mutually recursive functions using "with" *) 82Fixpoint is_even (n : nat) : bool := match n with 83 | 0 => true 84 | (S n) => is_odd n 85end with 86 is_odd n := match n with 87 | 0 => false 88 | (S n) => is_even n 89 end. 90 91(* As Coq is a total programming language, it will only accept programs when 92 it can understand they terminate. It can be most easily seen when the 93 recursive call is on a pattern matched out subpiece of the input, as then 94 the input is always decreasing in size. Getting Coq to understand that 95 functions terminate is not always easy. See the references at the end of 96 the article for more on this topic. *) 97 98(* Anonymous functions use the following syntax: *) 99 100Definition my_square : nat -> nat := fun x => x * x. 101 102Definition my_id (A : Type) (x : A) : A := x. 103Definition my_id2 : forall A : Type, A -> A := fun A x => x. 104Compute my_id nat 3. (* 3 : nat *) 105 106(* You can ask Coq to infer terms with an underscore *) 107Compute my_id _ 3. 108 109(* An implicit argument of a function is an argument which can be inferred 110 from contextual knowledge. Parameters enclosed in {} are implicit by 111 default *) 112 113Definition my_id3 {A : Type} (x : A) : A := x. 114Compute my_id3 3. (* 3 : nat *) 115 116(* Sometimes it may be necessary to turn this off. You can make all 117 arguments explicit again with @ *) 118 119Compute @my_id3 nat 3. 120 121(* Or give arguments by name *) 122Compute my_id3 (A:=nat) 3. 123 124(* Coq has the ability to extract code to OCaml, Haskell, and Scheme *) 125Require Extraction. 126Extraction Language OCaml. 127Extraction "factorial.ml" factorial. 128(* The above produces a file factorial.ml and factorial.mli that holds: 129 130type nat = 131| O 132| S of nat 133 134(** val add : nat -> nat -> nat **) 135 136let rec add n m = 137 match n with 138 | O -> m 139 | S p -> S (add p m) 140 141(** val mul : nat -> nat -> nat **) 142 143let rec mul n m = 144 match n with 145 | O -> O 146 | S p -> add m (mul p m) 147 148(** val factorial : nat -> nat **) 149 150let rec factorial n = match n with 151| O -> S O 152| S n' -> mul n (factorial n') 153*) 154 155 156(*** Notation ***) 157 158(* Coq has a very powerful Notation system that can be used to write 159 expressions in more natural forms. *) 160 161Compute Nat.add 3 4. (* 7 : nat *) 162Compute 3 + 4. (* 7 : nat *) 163 164(* Notation is a syntactic transformation applied to the text of the program 165 before being evaluated. Notation is organized into notation scopes. Using 166 different notation scopes allows for a weak notion of overloading. *) 167 168(* Imports the Zarith module holding definitions related to the integers Z *) 169 170Require Import ZArith. 171 172(* Notation scopes can be opened *) 173Open Scope Z_scope. 174 175(* Now numerals and addition are defined on the integers. *) 176Compute 1 + 7. (* 8 : Z *) 177 178(* Integer equality checking *) 179Compute 1 =? 2. (* false : bool *) 180 181(* Locate is useful for finding the origin and definition of notations *) 182Locate "_ =? _". (* Z.eqb x y : Z_scope *) 183Close Scope Z_scope. 184 185(* We're back to nat being the default interpretation of "+" *) 186Compute 1 + 7. (* 8 : nat *) 187 188(* Scopes can also be opened inline with the shorthand % *) 189Compute (3 * -7)%Z. (* -21%Z : Z *) 190 191(* Coq declares by default the following interpretation scopes: core_scope, 192 type_scope, function_scope, nat_scope, bool_scope, list_scope, int_scope, 193 uint_scope. You may also want the numerical scopes Z_scope (integers) and 194 Q_scope (fractions) held in the ZArith and QArith module respectively. *) 195 196(* You can print the contents of scopes *) 197Print Scope nat_scope. 198(* 199Scope nat_scope 200Delimiting key is nat 201Bound to classes nat Nat.t 202"x 'mod' y" := Nat.modulo x y 203"x ^ y" := Nat.pow x y 204"x ?= y" := Nat.compare x y 205"x >= y" := ge x y 206"x > y" := gt x y 207"x =? y" := Nat.eqb x y 208"x <? y" := Nat.ltb x y 209"x <=? y" := Nat.leb x y 210"x <= y <= z" := and (le x y) (le y z) 211"x <= y < z" := and (le x y) (lt y z) 212"n <= m" := le n m 213"x < y <= z" := and (lt x y) (le y z) 214"x < y < z" := and (lt x y) (lt y z) 215"x < y" := lt x y 216"x / y" := Nat.div x y 217"x - y" := Init.Nat.sub x y 218"x + y" := Init.Nat.add x y 219"x * y" := Init.Nat.mul x y 220*) 221 222(* Coq has exact fractions available as the type Q in the QArith module. 223 Floating point numbers and real numbers are also available but are a more 224 advanced topic, as proving properties about them is rather tricky. *) 225 226Require Import QArith. 227 228Open Scope Q_scope. 229Compute 1. (* 1 : Q *) 230 231(* Only 1 and 0 are interpreted as fractions by Q_scope *) 232Compute 2. (* 2 : nat *) 233Compute (2 # 3). (* The fraction 2/3 *) 234Compute (1 # 3) ?= (2 # 6). (* Eq : comparison *) 235Close Scope Q_scope. 236 237Compute ( (2 # 3) / (1 # 5) )%Q. (* 10 # 3 : Q *) 238 239 240(*** Common data structures ***) 241 242(* Many common data types are included in the standard library *) 243 244(* The unit type has exactly one value, tt *) 245Check tt. (* tt : unit *) 246 247(* The option type is useful for expressing computations that might fail *) 248Compute None. (* None : option ?A *) 249Check Some 3. (* Some 3 : option nat *) 250 251(* The type sum A B allows for values of either type A or type B *) 252Print sum. 253Check inl 3. (* inl 3 : nat + ?B *) 254Check inr true. (* inr true : ?A + bool *) 255Check sum bool nat. (* (bool + nat)%type : Set *) 256Check (bool + nat)%type. (* Notation for sum *) 257 258(* Tuples are (optionally) enclosed in parentheses, items are separated 259 by commas. *) 260Check (1, true). (* (1, true) : nat * bool *) 261Compute prod nat bool. (* (nat * bool)%type : Set *) 262 263Definition my_fst {A B : Type} (x : A * B) : A := match x with 264 | (a,b) => a 265 end. 266 267(* A destructuring let is available if a pattern match is irrefutable *) 268Definition my_fst2 {A B : Type} (x : A * B) : A := let (a,b) := x in 269 a. 270 271(*** Lists ***) 272 273(* Lists are built by using cons and nil or by using notation available in 274 list_scope. *) 275Compute cons 1 (cons 2 (cons 3 nil)). (* (1 :: 2 :: 3 :: nil)%list : list nat *) 276Compute (1 :: 2 :: 3 :: nil)%list. 277 278(* There is also list notation available in the ListNotations modules *) 279Require Import List. 280Import ListNotations. 281Compute [1 ; 2 ; 3]. (* [1; 2; 3] : list nat *) 282 283 284(* There is a large number of list manipulation functions available, 285 including: 286 287• length 288• head : first element (with default) 289• tail : all but first element 290• app : appending 291• rev : reverse 292• nth : accessing n-th element (with default) 293• map : applying a function 294• flat_map : applying a function returning lists 295• fold_left : iterator (from head to tail) 296• fold_right : iterator (from tail to head) 297 298 *) 299 300Definition my_list : list nat := [47; 18; 34]. 301 302Compute List.length my_list. (* 3 : nat *) 303 304(* All functions in coq must be total, so indexing requires a default value *) 305Compute List.nth 1 my_list 0. (* 18 : nat *) 306Compute List.map (fun x => x * 2) my_list. (* [94; 36; 68] : list nat *) 307Compute List.filter (fun x => Nat.eqb (Nat.modulo x 2) 0) my_list. 308 (* [18; 34] : list nat *) 309Compute (my_list ++ my_list)%list. (* [47; 18; 34; 47; 18; 34] : list nat *) 310 311(*** Strings ***) 312 313Require Import Strings.String. 314 315(* Use double quotes for string literals. *) 316Compute "hi"%string. 317 318Open Scope string_scope. 319 320(* Strings can be concatenated with the "++" operator. *) 321Compute String.append "Hello " "World". (* "Hello World" : string *) 322Compute "Hello " ++ "World". (* "Hello World" : string *) 323 324(* Strings can be compared for equality *) 325Compute String.eqb "Coq is fun!" "Coq is fun!". (* true : bool *) 326Compute "no" =? "way". (* false : bool *) 327 328Close Scope string_scope. 329 330(*** Other Modules ***) 331 332(* Other Modules in the standard library that may be of interest: 333 334• Logic : Classical logic and dependent equality 335• Arith : Basic Peano arithmetic 336• PArith : Basic positive integer arithmetic 337• NArith : Basic binary natural number arithmetic 338• ZArith : Basic relative integer arithmetic 339 340• Numbers : Various approaches to natural, integer and cyclic numbers 341 (currently axiomatically and on top of 2^31 binary words) 342• Bool : Booleans (basic functions and results) 343 344• Lists : Monomorphic and polymorphic lists (basic functions and results), 345 Streams (infinite sequences defined with co-inductive types) 346• Sets : Sets (classical, constructive, finite, infinite, power set, etc.) 347• FSets : Specification and implementations of finite sets and finite maps 348 (by lists and by AVL trees) 349• Reals : Axiomatization of real numbers (classical, basic functions, 350 integer part, fractional part, limit, derivative, Cauchy series, 351 power series and results,...) 352• Relations : Relations (definitions and basic results) 353• Sorting : Sorted list (basic definitions and heapsort correctness) 354• Strings : 8-bit characters and strings 355• Wellfounded : Well-founded relations (basic results) 356 *) 357 358(*** User-defined data types ***) 359 360(* Because Coq is dependently typed, defining type aliases is no different 361 than defining an alias for a value. *) 362 363Definition my_three : nat := 3. 364Definition my_nat : Type := nat. 365 366(* More interesting types can be defined using the Inductive vernacular. 367 Simple enumeration can be defined like so *) 368 369Inductive ml := OCaml | StandardML | Coq. 370Definition lang := Coq. (* Has type "ml". *) 371 372(* For more complicated types, you will need to specify the types of the 373 constructors. *) 374 375(* Type constructors don't need to be empty. *) 376Inductive my_number := plus_infinity 377 | nat_value : nat -> my_number. 378Compute nat_value 3. (* nat_value 3 : my_number *) 379 380 381(* Record syntax is sugar for tuple-like types. It defines named accessor 382 functions for the components. Record types are defined with the notation 383 {...} *) 384 385Record Point2d (A : Set) := mkPoint2d { x2 : A ; y2 : A }. 386(* Record values are constructed with the notation {|...|} *) 387Definition mypoint : Point2d nat := {| x2 := 2 ; y2 := 3 |}. 388Compute x2 nat mypoint. (* 2 : nat *) 389Compute mypoint.(x2 nat). (* 2 : nat *) 390 391(* Types can be parameterized, like in this type for "list of lists of 392 anything". 'a can be substituted with any type. *) 393 394Definition list_of_lists a := list (list a). 395Definition list_list_nat := list_of_lists nat. 396 397(* Types can also be recursive. Like in this type analogous to 398 built-in list of naturals. *) 399 400Inductive my_nat_list := 401 EmptyList | NatList : nat -> my_nat_list -> my_nat_list. 402 403Compute NatList 1 EmptyList. (* NatList 1 EmptyList : my_nat_list *) 404 405(** Matching type constructors **) 406 407Inductive animal := Dog : string -> animal | Cat : string -> animal. 408 409Definition say x := 410 match x with 411 | Dog x => (x ++ " says woof")%string 412 | Cat x => (x ++ " says meow")%string 413 end. 414 415Compute say (Cat "Fluffy"). (* "Fluffy says meow". *) 416 417(** Traversing data structures with pattern matching **) 418 419(* Recursive types can be traversed with pattern matching easily. 420 Let's see how we can traverse a data structure of the built-in list type. 421 Even though the built-in cons ("::") looks like an infix operator, 422 it's actually a type constructor and can be matched like any other. *) 423Fixpoint sum_list l := 424 match l with 425 | [] => 0 426 | head :: tail => head + (sum_list tail) 427 end. 428 429Compute sum_list [1; 2; 3]. (* Evaluates to 6 *) 430 431 432(*** A Taste of Proving ***) 433 434(* Explaining the proof language is out of scope for this tutorial, but here 435 is a taste to whet your appetite. Check the resources below for more. *) 436 437(* A fascinating feature of dependently type based theorem provers is that 438 the same primitive constructs underly the proof language as the 439 programming features. For example, we can write and prove the 440 proposition A and B implies A in raw Gallina *) 441 442Definition my_theorem : forall A B, A /\ B -> A := 443 fun A B ab => match ab with 444 | (conj a b) => a 445 end. 446 447(* Or we can prove it using tactics. Tactics are a macro language to help 448 build proof terms in a more natural style and automate away some 449 drudgery. *) 450 451Theorem my_theorem2 : forall A B, A /\ B -> A. 452Proof. 453 intros A B ab. destruct ab as [ a b ]. apply a. 454Qed. 455 456(* We can easily prove simple polynomial equalities using the 457 automated tactic ring. *) 458 459Require Import Ring. 460Require Import Arith. 461Theorem simple_poly : forall (x : nat), (x + 1) * (x + 2) = x * x + 3 * x + 2. 462 Proof. intros. ring. Qed. 463 464(* Here we prove the closed form for the sum of all numbers 1 to n using 465 induction *) 466 467Fixpoint sumn (n : nat) : nat := 468 match n with 469 | 0 => 0 470 | (S n') => n + (sumn n') 471 end. 472 473Theorem sum_formula : forall n, 2 * (sumn n) = (n + 1) * n. 474Proof. intros n. induction n. 475 - reflexivity. (* 0 = 0 base case *) 476 - simpl. ring [IHn]. (* induction step *) 477Qed.

With this we have only scratched the surface of Coq. It is a massive ecosystem with many interesting and peculiar topics leading all the way up to modern research.

Further reading