coq-club AT inria.fr
Subject: The Coq mailing list
List archive
- From: Marcel Ullrich <s8maullr AT stud.uni-saarland.de>
- To: coq-club AT inria.fr
- Subject: Re: [Coq-Club] termination when branching with fmaps
- Date: Fri, 19 Feb 2021 17:23:52 +0100
- Authentication-results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=s8maullr AT stud.uni-saarland.de; spf=Pass smtp.mailfrom=s8maullr AT stud.uni-saarland.de; spf=None smtp.helo=postmaster AT thyone.hiz-saarland.de
- Ironport-phdr: 9a23:oAqh9xfCzYo5U172RSTOgG+UlGMj4u6mDksu8pMizoh2WeGdxcS8YR7h7PlgxGXEQZ/co6odzbaP4ua/Byddvt6oizMrSNR0TRgLiMEbzUQLIfWuLgnFFsPsdDEwB89YVVVorDmROElRH9viNRWJ+iXhpTEdFQ/iOgVrO+/7BpDdj9it1+C15pbffxhEiCCybL9vKBi6twfcu8gZjYZiKKs61wfErGZPd+lK321jOEidnwz75se+/Z5j9zpftvc8/MNeUqv0Yro1Q6VAADspL2466svrtQLeTQSU/XsTTn8WkhtTDAfb6hzxQ4r8vTH7tup53ymaINH2QLUpUjms86tnVBnlgzoBOjUk8m/Yl9ZwgbpGrhy/qRxxw43abo+bO/VxfKzSYcgXSnBdUstLTSFNHo2xYokJAuEcPehYtY79p14WoBW5HwasHv/gxSFMhnTr06I61+AhERvH3AM8H9IFrXPZrM72OacXS++10a3IzTHZb/5Nwjf99JXIfQ07rfGRW7JwcNPdyVI1GAzflFWQrZbqPzWI2egXrmeU8fNtWOSygGEotw9/uCKgxtswiobXnIIVzEjJ+Dl3zYorOdG1TE92bN2mHZZUqyyXN5Z7T8AiTWx1pis0xbILtYK/cSYEyJkqyR7SZv2afoWJ/B7uW+ecLDVkiH9jZbmxhA6y/FC9xuDyWcS4ylJHoytfntTOrHwByRLe5tafRvZ//EqtwyiD2x3J5u1aIU05lbDXJ4Mlz7M/kJcYrF7NETXsmErsia+bbkUk9fas6+Tgerjmup+cNo9zigH4LKsigMy/AeU5MwQXRGiU4/6z1Kfn/ULjRrVFk+c6nbTHv5zCJMQboLC2AxNN34o+5RuyAC2q3dAZkHUdLl9JYgyLgob3N13WJfD3F/a/g1CikDdxwPDGO6XsAo7OI3jGirjhYLJ960pGyAco1tBf+49UBawbLPLuXE/xtcXUDgQjPAOu2ebnDM9y1oUDVm6VH6CWLrvesUWU6eI3P+mMeIgVtS7hJPgi/v7ilGM2mVsAfaayxpYXc3C5HvF+I0qDe3bsg9EBEX0LvgUkVuDqhkeCAnZvYCO5WLt57TUmAqqnC53CT8ajmu+vxiC+S7hffGtLDhixFXPydo6EE6MXOCebP8tliBQfSaWtDZIn1FS1vQbgz7NhIqzY93tL5trYyNFp6riLxlkJ/jtuApHFijDffyRPhmoNAgQO8uV6qE15xE2E1PIi0edECNAV+vVIFxwzPITYxup2Tdz/CFuYI4W5DW2+S9DjOgkfC9I8x9hUPxRhG8SliB2F3yu4RqQcnqaPDZo4tK7RjSCoe5RNjk3e3axktGEIB9NVPDf81LVj6gSVGojI1l6QnryufKIQmiLApj+O
Hi Lorenzo,
In principle such things can be solved by our MetaCoq plugin for
nested inductive types, but you can also use the principle
manually as follows:
We define the functor for easier use:
```
Definition F X := {fmap nat -> X}.
Inductive fmap_tree :=
| fmap_leaf (n : nat)
| fmap_node (n : nat) (branching : F fmap_tree).
```
We then define what is means assumption should
be fulfilled for the nested argument.
Namely, every subterm of type fmap_tree should have a height.
```
Definition FAssumption {X} (P:X->Type) (br:F X) :=
forall x y, br.[? x]=Some y -> P y.
Definition FProof {X} (P:X->Type) (f:forall x, P x) (br:F X) :
FAssumption P br.
move : br => [? ?] x;case: fndP => ? ?.
- by injection 1 as <-.
- congruence.
Defined.
```
These two definitions could be registered and used by the plugin.
Alternatively, we can use them manually to derive the induction
principle by hand:
```
Definition fmap_tree_nind
: forall p : fmap_tree -> Type,
(forall n : nat, p (fmap_leaf n)) ->
(forall (n : nat) (branching : F fmap_tree),
FAssumption p branching ->
p (fmap_node n branching)) ->
forall inst : fmap_tree, p inst.
Proof.
intros p HL HN.
refine (fix f inst := _).
destruct inst.
- apply HL.
- apply HN,FProof,f.
Defined.
```
Coq accepts the definition of fmap_tree_nind as FProof only
applies f to structurally
smaller instances of fmap_tree.
The definition of depth can be adapted to use fmap_tree_nind:
We fold over every number in the domain of br and if the result of
br.[?x] is not None, the recursively determined depth can be used.
```
Definition depth (T : fmap_tree) : nat.
refine(fmap_tree_nind (fun _ => nat)
(fun n => 0)
(fun n br h =>
(foldr maxn 0 (map (fun x => _
) (enum_fset (domf br)))).+1
) T).
destruct (br.[?x]) eqn:H.
- exact (h x _ H).
- exact 0.
Defined.
```
Two small testcases:
```
Compute (depth (fmap_leaf 42)). (* 0 *)
Definition t1 := fmap_node 3 fmap0.
Compute (depth t1). (* 1 *)
```
Best,
Marcel
For fixpoints on nested inductive types, you must make sure to apply
your function to a subterm. In your case, that means `depth` must end up
applied to `br x` for any `x`.
> Fixpoint depth (T : fmap_tree) : nat :=
> match T with
> | fmap_leaf n => 0
> | fmap_node n br => (maxn_f_codom id (fun x => depth (br x))).+1
> end.
Now it is clear that the only location where `depth` is called
recursively is in fact good. The exact rules are a little looser than
that, but then you have to be aware of those rules and of the precise
definition of every function that separates `depth` from `br`; it's not
sufficient to understand what those functions do extensionally.
Cheers,
Li-yao
On 2/18/2021 1:32 PM, Lorenzo Gheri wrote:
> Hi All,
>
> I have defined the following datatype:
>
> From mathcomp.ssreflect Require Import all_ssreflect.
> From mathcomp Require Import finmap.
> Open Scope fset.
> Open Scope fmap.
>
> Inductive fmap_tree :=
> | fmap_leaf (n : nat)
> | fmap_node (n : nat) (branching : {fmap nat -> fmap_tree}).
>
> I would really like to keep this definition, namely to use finite maps
> (fmap from the math-comp libraries) instead of lists. I however run into
> problems when defining depth:
>
> Definition maxn_f_codom {A:Type} (f: A -> nat) (br: {fmap nat -> A}):=
> foldr maxn 0 (map (fun x=> match (br.[?x]) with
> | None => 0
> | Some T' => f T'
> end)
> (enum_fset (domf br)) ).
>
>
> Fixpoint depth (T : fmap_tree) : nat :=
> match T with
> | fmap_leaf n => 0
> | fmap_node n br => (maxn_f_codom depth br).+1
> end.
>
> In particular the definition of maxn_f_codom above---which could as well
> be inlined in the depth definition---is accepted by Coq with no issues,
> but the Fixpoint for depth is ill-formed. I thought I could easily use
> enum_fset for turning the finite domain of the fmap into a list and then
> termination would have been guaranteed. I was being too naif! :)
>
> Before I give up altogether and go back to branching with lists, is
> there any way for me to convince Coq that fmaps are OK as well?
>
> Many thanks,
> Lorenzo
>
>
>
- [Coq-Club] termination when branching with fmaps, Lorenzo Gheri, 02/18/2021
- Re: [Coq-Club] termination when branching with fmaps, Li-yao Xia, 02/18/2021
- Re: [Coq-Club] termination when branching with fmaps, Lorenzo Gheri, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Matthieu Sozeau, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Laurent Thery, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Lorenzo Gheri, 02/20/2021
- Re: [Coq-Club] termination when branching with fmaps, Laurent Thery, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Marcel Ullrich, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Matthieu Sozeau, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Lorenzo Gheri, 02/19/2021
- Re: [Coq-Club] termination when branching with fmaps, Li-yao Xia, 02/18/2021
Archive powered by MHonArc 2.6.19+.