Coq学习——《Software-Foundation》Volume1.4-Poly
Poly
Polymorphism
Continue basic concepts of functional programming. Begin with polymoriphism.
Polymorphic Lists
List elements: One type -> Other types.
The natlist defined in the last chap.
1 |
|
Coq supports polymorphic inductive type definitions.
1 |
|
A binding for [X] has been added to the function header.
What sort of thing is [list] itself? A good way to think about it is that the definition of [list] is a function from [Type]s to [Inductive] definitions.
Now when we use them, we must provide a first argu. that is the type of the list they are building.
WHAT TYPE?
1 |
|
Always a type argument. No! Reducing this annotation burden.
Type Argument Synthesis
Thanks to type inference, we don't always have to write explicit type annotations everywhere (including [Type] when we use polymoriphism).
1 |
|
[X] use as the first argu. of cons. So it must be a Type. We don't have to write its annotation in the first line.
Type Argument Synthesis
Second argu must be an element of [X] (the first element). Let Coq do it. Write a "hole" [_]. "Please try to figure out for yourself what belongs here."
1 |
|
Implicit Arguments.
In fact, we can go further and even avoid writing [_]'s in most cases by telling Coq always to infer the type argument(s) of a given function.
Curly braces around any arguments to be treated as implicit.
1 |
|
1 |
|
We will use the latter style whenever possible, but we will continue to use explicit [Argument] declarations for [Inductive] constructors. The reason for this is that marking the parameter of an inductive type as implicit causes it to become implicit for the type itself, not just for its constructors. For instance, consider the following alternative definition of the [list] type:
Supplying Type Arguments Explicitly
For enough local information to determine a type argument.
@
prefix the function name.
Exercise: re-proof the theorm in Pilymorphism.
Polymorphic Pairs
Polymorphic Pairs, often called Products.
annotation type_scope?
Tells Coq that this abbreviation should only be used when parsing types, not when parsing expressions. This avoids a clash with the multiplication symbol.
1 |
|
We can find the differences.
From
1 |
|
To
1 |
|
Becareful to [(x,y)] and [X*Y]. Remeber the first is a value built from two other values, while [X*Y] is a type built from two other types.
First use let...in
in Coq, remember to use :=
instead of =
which is usually used in OCaml.
1 |
|
Polymorphic Options
After polymorphic lists and pairs, now options.
Functions as Data
Functions as first-class citizens.
Like most modern programming languages -- especially other "functional" languages, including OCaml, Haskell, Racket, Scala, Clojure, etc. -- Coq treats functions as first-class citizens, allowing them to be passed as arguments to other functions, returned as results, stored in data structures, etc.
Higher-Order Functions
Manipulate other functions are often called higher-order functions.
操作其他的函数——高阶函数。
Learning this sub-chap is similar to the learning of functional programming in OCaml.
Filter
过滤器
“Filtering” the list.
1 |
|
Anonymous Functions
Construct a function "on the fly" without declaring it at the top or giving it a name.
随时使用,用完即扔(逃
Exercise: partition.
(Github repo)
Map
Map apply the function to each ele. in the lists.
About map_rev
, first prove the lemma about map and app.
Here.
1 |
|
Fold
An even more powerful higher-order function is called fold. This function is the inspiration for the "[reduce]" operation that lies at the heart of Google's map/reduce distributed programming framework.
Functions That Construct Functions
Curring Functions.
The function with type \(\forall X, X \rightarrow nat \rightarrow X\) is, in fact, same to \(\forall X, X \rightarrow (nat \rightarrow X)\). So we can def a func with one argu and return a \(\nat \rightarrow X\) func.
When we only give the first argu, we get a new func. This kind of usage is also named as partial application.
In Coq, a function [f : A -> B -> C] really has the type [A -> (B -> C)]. That is, if you give [f] a value of type [A], it will give you function [f' : B -> C]. If you then give [f'] a value of type [B], it will return a value of type [C]. This allows for partial application, as in [plus3]. Processing a list of arguments with functions that return functions is called currying, in honor of the logician Haskell Curry.
1 |
|
Additional Exercise
[reflexivity] simplifies expressions a bit more aggressively than [simpl] does.
Currying and uncrrying with the proof of equ.
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!