Coq中的列表理解

时间:2014-03-23 19:23:32

标签: list-comprehension monads coq

我想在Coq中使用Monad理解。 由于我认为我很难实现需要MonadPlus的符号,例如[ x | x <- m, x < 4 ],我没有尝试实现这样的符号。 因此,我写了下面的代码。

Notation "[ e | x <- m1 , .. , y <- m2 ]"
  := (m1 >>= (fun x => .. (m2 >>= (fun y => e)) ..))
  (x closed binder, y closed binder).

但是,它没有工作,我收到了这个错误。

Error: m1 is expected to occur in binding position in the right-hand side.

我认为Coq将"[ m | x <- m1 , .. , y <- m2 ]"(Coq代码)解释为"[ m | x <- ( m1 , .. , y ) <- m2 ]"(伪代码)。 但我没有解决这个问题的方法。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我不知道Notation s是否可以这样做。我能得到的最接近的是写[ e | x <- mx , ... , y <- my ]而不是写[ x <- mx , ... , y <- my | e ]

你可以这样做:

Require Import List.

Fixpoint join {a : Type} (xss : list (list a)) : list a :=
match xss with
 | nil           => nil
 | (cons xs xss) => xs ++ join xss
end.

Definition bind {a b : Type} (xs : list a) (f : a -> list b) : list b :=
  join (map f xs).

Notation "[ e" :=  e (at level 3).
Notation "x '<-' mx '|' e ']'" := (bind mx (fun x => cons e nil))
  (at level 2).
Notation "x '<-' mx ',' f"     := (bind mx (fun x => f))
  (right associativity, at level 2).

你现在可以这样写:

Goal forall xs ys, { zs | zs = [ x <- xs, y <- map (plus x) ys | y - x ] }.

然而,这个脱落的版本看起来很糟糕,目标很难阅读。如果它仅用于编程,那就非常好了。你甚至可以输入一些额外的符号,例如范围:

Fixpoint range0 (n : nat) : list nat :=
match n with
 | O   => cons O nil
 | S m => cons n (range0 m)
end.

Definition range (m n : nat) : list nat := map (plus m) (rev (range0 (n - m))).

Notation "m -- n ']'" := (range m n) (at level 2).

让你可以写下这样的内容:

Goal { xs | xs = [ x <- [ 1 -- 3 ]
                 , y <- [ 1 -- x ]
                 | x + y ] }.