我想在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 ]"
(伪代码)。
但我没有解决这个问题的方法。任何帮助将不胜感激。
答案 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 ] }.