Coq 我怎样才能创建一个多态的;地图xs f";功能? 问题的陈述。

Coq 我怎样才能创建一个多态的;地图xs f";功能? 问题的陈述。,coq,parametric-polymorphism,Coq,Parametric Polymorphism,考虑一下map的定义: Fixpoint map (xs: list nat): (nat -> nat) -> list nat := match xs with | nil => fun _ => nil | x::xs' => fun f => (f x) :: (map xs' f) end. 它的工作原理如下: Coq < Eval simpl in map (1::2::3::List.nil) (fun x => x + 1).

考虑一下
map
的定义:

Fixpoint map (xs: list nat): (nat -> nat) -> list nat := match xs with
| nil => fun _ => nil
| x::xs' => fun f => (f x) :: (map xs' f)
end.
它的工作原理如下:

Coq < Eval simpl in map (1::2::3::List.nil) (fun x => x + 1).
     = 2 :: 3 :: 4 :: nil
     : list nat
但是在Coq中,我不明白我可以把这个
放在哪里

我的努力。 解释
Fixpoint
的语法如下:

Fixpoint ident binders{struct ident}类型?:=术语

-因此,显然,在语法中没有一个量词可以将类型变量绑定到绑定器和类型上。我试着通过猜测把所有的
放在这里和那里,但我没能做到

我可以看到如何在不接触binders部分的情况下,使type部分在函数参数的结果类型中具有多态性:

-但不幸的是,这也给出了一个错误,对我来说,这已经够神秘的了:

In environment
map : list nat -> forall B : Type, (nat -> B) -> list B
xs : list nat
T : Type
The term "nil" has type "list ?A" while it is expected to have type
 "(nat -> T) -> list T".
所以,即使对于这个更简单的情况,我也没有解决方案


那么,可以做些什么呢?在Coq中,
Fixpoint
命令只是
fix
术语构造函数的包装,它允许我们定义匿名递归函数。
map
的直接定义如下:

map :: forall a b. [a] -> (a -> b) -> [b]
map xs = case xs of
    [ ]     -> \_ -> [ ]
    (x:xs') -> \f -> f x: map xs' f
Require Import Coq.Lists.List.
Import ListNotations.

Definition map_anon : forall A B, (A -> B) -> list A -> list B :=
  fix map A B (f : A -> B) (l : list A) : list B :=
    match l with
    | [] => []
    | x :: l => f x :: map A B f l
    end.
这在道德上等同于以下定义:

Fixpoint map A B (f : A -> B) (l : list A) : list B :=
  match l with
  | [] => []
  | x :: l => f x :: map A B f l
  end.

请注意,
A
B
被绑定为正则变量:在Coq中,类型和术语之间没有区别,这些声明使Coq将它们的类型推断为
Type
。定义不需要任何限定符。

您可以在函数名称后列出所有参数,包括类型参数。您将把任何依赖于其他参数的参数放在它们所依赖的参数之后

Fixpoint map (A B: Type) (xs: list A) (f: A -> B): list B :=
[...]
如果您喜欢所有s的
,只需将所有内容(递归参数及其依赖的任何参数除外)移到
之后即可

Fixpoint map (A B: Type) (xs: list A): forall (f: A -> B), list B :=
[...]
这里需要注意两件事。由于
f
之后的内容不依赖于
f
,因此可以使用
->
表示法。这纯粹是符号,没有任何语义上的区别

Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
[...]
另一件需要注意的事情是,当参数位于
之后时,我们必须定义一个函数,而不仅仅是
列表B中的某个函数

Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
fun f => [...]

这就是为什么出现错误
术语“nil”的类型为“list?A”,而预期它的类型为“(nat->T)->list T”。
。我们需要一个函数,而不仅仅是
listb
类型的函数,这就是
nil
是什么。

不能像您建议的那样使用
Fixpoint
命令,它必须显式地接受至少一个参数(递归参数),因此,只有您的第一个示例是正确的。请注意,您还可以
打印映射。
查看在标准库中是如何完成的。这里让您感到困惑的神秘错误消息是,在Haskell中,类型参数仅在类型中提到。在Coq中,它们是函数的实际参数,默认情况下不是隐式的。如果您编写
,那么您得到的错误与您在Haskell中得到的错误相同。。。[]->[]…
的大小写xs,其余代码保持不变
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
fun f => [...]