I am trying to make a weighted tree library for some stuff I would like to do in Coq. Each edge of a tree should have a real number valued weight. One of the operations I want is a prune function which prunes leaf edges from the tree if they have weight 0.
The following code is my set-up for the trees:
Require Import Coq.Reals.Reals.
Require Import Coq.Lists.List.
Section WeightedTrees.
Inductive wtree' (A : Type) : Type :=
| Null : wtree' A
| LNode : A -> wtree' A
| INode : A -> list (wtree' A) -> wtree' A.
Inductive Wtype (A : Type) : Type := W: R -> A -> Wtype A.
Definition wtree (A : Type) := wtree' (Wtype A).
(* Helper: checks whether a tree contains an element *)
Fixpoint wt_contains {A : Type} (a : A) (t : wtree A) : Prop :=
match t with
| Null => False
| LNode (W w a') => a' = a
| INode (W w a') l => a' = a \/ (fold_left or (map (wt_contains a) l) True)
end.
Here is my current attempt at a prune function. Coq does not accept it because 0%R is not a co-inductive type.
Fixpoint wt_prune_list {A : Type} (l:list (wtree A)) : (list (wtree A)) :=
match l with
| nil => nil
| (cons Null l) => (cons (Null (Wtype A)) (wt_prune_list l))
| (cons (INode w l') l) => (cons ((INode (Wtype A)) w l') ((wt_prune_list A) l))
| (cons (LNode (W w a')) l) =>
if w = 0%R then
(wt_prune_list l)
else
(cons (LNode (W w a')) (wt_prune_list l))
end.
So I have a few questions:
- Most importantly: How do I fix the above code so that it prunes the tree of leaf edges of zero weight?
- Does checking whether something like
w=0%R
even make sense? I suppose one should think of this as saying if we have a proof thatw = 0%R
. Is this right? - Are there shorter ways of writing lines like:
(cons (INode w l') l) => (cons ((INode (Wtype A)) w l') ((wt_prune_list A) l))
? I know I could have matched with(cons (INode _) _)
but then it seems I have no good way of constructing the other side. It would be nice if there was something like(cons (INode _1) _2) => (cons (INode _1) ((wt_prune_list A) _2)
where Coq could figure out that_1
represents multiple arguments in the same way that it does with_
.