Recursive use of typeclass methods in Coq - coq

Is there a way to use recursion with Coq's typeclasses? Like for e.g., in defining show for lists, if you want to call the show function for lists recursively, then you will have to use a fixpoint like so:
Require Import Strings.String.
Require Import Strings.Ascii.
Local Open Scope string_scope.
Class Show (A : Type) : Type :=
{
show : A -> string
}.
Section showNormal.
Instance showList {A : Type} `{Show A} : Show (list A) :=
{
show :=
fix lshow l :=
match l with
| nil => "[]"
| x :: xs => show x ++ " : " ++ lshow xs
end
}.
End showNormal.
Which is all well and good, but what if I want to define some helper function that I'll use for defining Show instances? Like I want to create a more DAZZLING show function called magicShow that prints stars around something...
Definition magicShow {A : Type} `{Show A} (a : A) : string :=
"** " ++ show a ++ " **".
Instance showMagicList {A : Type} `{Show A} : Show (list A) :=
{
show :=
fix lshow l :=
match l with
| nil => "[]"
| x :: xs => show x ++ " : " ++ magicShow xs
end
}.
However, in this case Coq can't find a show instance for the list xs to pass to magicShow:
Error:
Unable to satisfy the following constraints:
In environment:
A : Type
H : Show A
lshow : list A -> string
l : list A
x : A
xs : list A
?H : "Show (list A)"
Is there any way to do this in general? I.e., can you define a method for a typeclass using functions that rely upon the typeclass instance that you're defining?

No, there's no way to do this. This works in Haskell because arbitrary recursive bindings are allowed, and the language doesn't care about the order of bindings. Coq is more restrictive on both fronts. This makes sense if you think about what the desugaring looks like: the recursive call to show would refer to the currently-being-defined instance by name, but that binding isn't in scope yet. And you can't make the instance itself a fixpoint because you're recursing on the structure of a type, not on a value of an algebraic data type.
Your inline fixpoint works for show, but the problem gets thornier if your method implementations refer to each other, such as
newtype MyInteger = MyInteger Integer
instance Num MyInteger where
MyInteger m + MyInteger n = MyInteger $ m + n
negate (MyInteger m) = MyInteger $ negate m
m - n = m + negate n
-- other methods
Here, the calls to (+) and negate in the definition of (-) needs to refer to the definitions of (+) and negate above, but this also doesn't work in Coq. The only solution is to define all your methods separately, manually referencing each other, and then define the instance simply by setting each method to the one you defined above. For example,
Inductive MyInteger := Mk_MyInteger : Integer -> MyInteger.
Definition add__MyInteger (m n : MyInteger) : MyInteger :=
let 'Mk_MyInteger m' := m in
let 'Mk_MyInteger n' := n in
Mk_MyInteger (add m' n').
Definition negate__MyInteger (m : MyInteger) : MyInteger :=
let 'Mk_MyInteger m' := m in
Mk_MyInteger (negate m').
Definition sub__MyInteger (m n : MyInteger) : MyInteger :=
add__MyInteger m (negate__MyInteger n).
Instance Num__MyInteger : Num MyInteger := {|
add := add__MyInteger;
negate := negate__MyInteger;
sub := sub__MyInteger;
(* other methods *)
|}.

If you must do this, it can be simulated by explicitly using the constructor of the underlying Record (since "Typeclasses are Records", to quote from Software Foundations [1]), which can be instantiated using the function(s) being defined as a fixpoint. I'll post three examples and explain where this can be useful.
The example you posted could be solved like this (all code tested for Coq 8.10.1):
Require Import Strings.String.
Local Open Scope list_scope.
Local Open Scope string_scope.
Class Show (A : Type) : Type :=
{
show : A -> string
}.
Definition magicShow {A : Type} `{Show A} (a : A) : string :=
"** " ++ show a ++ " **".
Print Show.
(* Record Show (A : Type) : Type := Build_Show { show : A -> string }
*)
Check Build_Show.
(* Build_Show : forall A : Type, (A -> string) -> Show A *)
Check #magicShow.
(* #magicShow : forall A : Type, Show A -> A -> string *)
Instance showMagicList {A : Type} `{Show A} : Show (list A) :=
{
show :=
fix lshow l :=
match l with
| nil => "[]"
| x :: xs => show x ++ " : " ++ #magicShow _ (#Build_Show _ lshow) xs
end
}.
If you are trying to define several typeclass methods like this, it's tricky to instantiate the record constructor, but it can be done by treating the functions as if they were defined by mutual recursion (although there doesn't necessarily have to be any actual mutual recursion). Here's a contrived example where Show now has two methods. Notice that the typeclass instance is added to the context with an anonymous let-in binding. Evidently, this is enough to satisfy Coq's typeclass resolution mechanism.
Require Import Strings.String.
Local Open Scope list_scope.
Local Open Scope string_scope.
Class Show (A : Type) : Type :=
{
show1 : A -> string
; show2 : A -> string
}.
Definition magicShow1 {A : Type} `{Show A} (a : A) : string :=
"** " ++ show1 a ++ " **".
Definition magicShow2 {A : Type} `{Show A} (a : A) : string :=
"** " ++ show2 a ++ " **".
Fixpoint show1__list {A : Type} `{Show A} (l : list A) : string :=
let _ := (#Build_Show _ show1__list show2__list) in
match l with
| nil => "[]"
| x :: xs => show1 x ++ " : " ++ magicShow1 xs
end
with show2__list {A : Type} `{Show A} (l : list A) : string :=
let _ := (#Build_Show _ show1__list show2__list) in
match l with
| nil => "[]"
| x :: xs => show1 x ++ " : " ++ magicShow2 xs
end.
Instance showMagicList {A : Type} `{Show A} : Show (list A) :=
{
show1 := show1__list
; show2 := show2__list
}.
So why would you want to do this? A good example is when you are defining decidable equality on (rose) trees. In the middle of the definition, we have to recursively appeal to decidable equality of list (tree A). We would like to use the standard library helper function Coq.Classes.EquivDec.list_eqdec [2], which shows how to pass decidable equality on a type A to list A. Since list_eqdec requires a typeclass instance (the very one we are in the middle of defining), we have to use the same trick above:
Require Import Coq.Classes.EquivDec.
Require Import Coq.Program.Utils.
Set Implicit Arguments.
Generalizable Variables A.
Inductive tree (A : Type) : Type :=
| leaf : A -> tree A
| node : list (tree A) -> tree A.
Program Instance tree_eqdec `(eqa : EqDec A eq) : EqDec (tree A) eq :=
{ equiv_dec := fix tequiv t1 t2 :=
let _ := list_eqdec tequiv in
match t1, t2 with
| leaf a1, leaf a2 =>
if a1 == a2 then in_left else in_right
| node ts1, node ts2 =>
if ts1 == ts2 then in_left else in_right
| _, _ => in_right
end
}.
Solve Obligations with unfold not, equiv, complement in * ;
program_simpl ; intuition (discriminate || eauto).
Next Obligation.
destruct t1;
destruct t2;
( program_simpl || unfold complement, not, equiv in *; eauto ).
Qed.
Solve Obligations with split; (intros; try unfold complement, equiv ; program_simpl).
(*
No more obligations remaining
tree_eqdec is defined
*)
Commentary: There is no constructor for creating a record of type EqDec (since it only has one class method), so to convince Coq that list (tree A) has decidable equality, the invocation is simply list_eqdec tequiv. For the uninitiated, Program here is simply allowing for holes in the definition of the instance to be filled in later as Obligations, which is more convenient than writing the appropriate proofs inline.

Related

Coq QuickChick : Making propery Checkable, Decidable, Arbitrary (Gen)

I am trying to test simple conjecture with QuickChick:
Conjecture lists_eq : forall (l : list string), l = l.
QuickChick lists_eq.
but I get this error:
Unable to satisfy the following constraints:
?arg_2 : "Checkable (forall l : list string, l = l)"
I know I need to make my property Instance of class Checkable, but how should I do it?
I made decidability on two lists (successfully)
Instance EqLists_Dec (x y : list string) : Dec (x = y).
I made Arbitrary for list (successfully)
Instance gen_list_string : Gen (list string)
But I couldn't make Property checkable, I know that bool type is Checkable in QC.
Here is the code, plese advice. Maybe I am doing it all in a wrong way.
From QuickChick Require Import QuickChick.
Require Import List ZArith. Import ListNotations.
Import QcNotation.
Set Warnings "-extraction-opaque-accessed,-extraction".
Require Import String. Local Open Scope string.
Definition genListString : G (list string) :=
elems_ ["Two" ; "Three"]
[
[ "One" ; "Nstasss" ; "SomeStr" ; "Yellow" ];
[ "111" ; "2222" ; "33333SomeStr" ; "44444Yellow" ]
].
(* Sample genListString. *)
Instance gen_list_string : Gen (list string) :=
{
arbitrary := genListString
}.
Notation "P '?'" :=
(match (#dec P _) with
| left _ => true
| right _ => false
end)
(at level 100).
Instance EqLists_Dec (x y : list string) : Dec (x = y).
Proof. dec_eq. Defined.
(* Problem in this function, couldn't make it work*)
Instance checkableDec `{P : Prop} `{Dec P} : Checkable P :=
{
checker p := if P? then ret ok else ret Failure
}.
Conjecture lists_eq : forall (l : list string), l = l.
QuickChick lists_eq.
(*
Unable to satisfy the following constraints:
?arg_2 : "Checkable (forall l : list string, l = l)"
*)
checkableDec already exists in QuickChick. You are actually missing a Shrink instance:
Instance Shrink_string : Shrink string :=
{| shrink x := [] |}.
To debug this you can Set Typeclasses Debug and then look at where the trace says no match for .... You have to be careful of false positives because there is backtracking, but with persistence and experience you'll get the hang of it.

What does the term "?T#{x:=t}", or a type with a question mark and at sign surrounding it mean in Coq?

I'm trying to write a function which removes the zeros from a list. Here is the first try of my implementation.
Require Import Nat.
Require Import List.
Fixpoint shrink (x : list nat) list nat := (* Mistake! Needs a : list nat *)
match x with
| nil => nil
| h :: t => if h =? 0 then shrink t else (h :: shrink t)
end.
However, I get this error:
Error:
In environment
shrink : forall (x : Datatypes.list Datatypes.nat)
(list0 : ?T) (nat : ?T0#{list:=list0}),
Datatypes.list ?T1#{x:=x; list:=list0; x1:=x}
x : list nat
list : ?T
nat : ?T0
h : Datatypes.nat
t : Datatypes.list Datatypes.nat
The term "shrink t" has type
"forall (list0 : ?T#{x:=t}) (nat : ?T0#{x:=t; list:=list0}),
Datatypes.list ?T1#{x:=t; list:=list0; x1:=t}"
while it is expected to have type "Datatypes.list ?T1#{x1:=h :: t}".
The correct function implementation is this:
Fixpoint shrink (x : list nat) : list nat :=
match x with
| nil => nil
| h :: t => if h =? 0 then shrink t else (h :: shrink t)
end.
But how am I supposed to interpret the error, in particular (list0 : ?T#{x:=t})? In particular,
Why is it list0 instead of list?
What does ? mean before the T?
What does the #{ ... } mean after the T?
For your first point, this is just a printing thing but essentially local variables names are just hints for Coq and it may not respect them to avoid confusion. Here it's probably because of the list := list0 we see later.
Letters preceded by ? are existential variables or evars, used for unification. Here it doesn't know what the type of list0 should be because you did not give any, but it knows it has to be something. So for now it's ?T and it will try to figure out later what it should be by looking at its uses.
For nat it's the same, but it also knows it might depend on some list and in this case its value should be list0 so it does the instantiation ?T0{list:=list0}. This notation is for substitution in evars.
I invite you to look at the documentation of evars in the manual to know more.

list constructors conflict in Coq

I have the following definitions in Coq:
Inductive list_variable : Type :=
| nil
| cons (s : string) (l : list_variable).
Fixpoint getElement (l : list_variable) (s : Variabile) (v : Address) {struct l} : Address :=
match l with
| nil => v
| str :: nil => (updateValues v ((updateState (updateState s "memPointer" (s("memPointer")+1)) str (s("memPointer"))) "memPointer") undef)
| str :: l => getElement l s v
end.
For some reason, the bottom and second line return Found a constructor of inductive type list while a constructor of list_variable is expected.
For reference, the long return on str::nil works fine in another place. It's for a memory-like simulation.
Any ideas as to why this happens?
The notation :: desugars to List.cons, whereas you want the constructor MyModule.cons. If you want to use ::, you must define a new notation for it:
Inductive list_variable : Type :=
| nil
| cons : ...
.
(* Redefine "::" for new list type *)
Infix "::" := cons.
If you intend to use the same notation for both list and list_variable, it will be necessary to manage notation scopes. Refer to the Coq manual, the section on notations.

Coq difficulties in defining constructors using coerced types

Definitions
I'm working on formalizing a typed lambda calculus in Coq, and to keep the notation manageable I've come to rely a lot on coercions. However, I've been running into some difficulties which seem odd.
Right now I'm trying to work with the following types:
type: A descriptor of an allowable type in the language (like function, Unit, etc...)
var: A variable type, defined as nat
VarSets: set of vars
Judgement: a var/my_type pair
ty_ctx: Lists of judgements.
ctx_join: Pairs of ty_ctx's describing disjoint sets of variables
The actual definitions are all given below, except for ctx_join which is given in the next block
(* Imports *)
Require Import lang_spec.
From Coq Require Import MSets.
Require Import List.
Import ListNotations.
Module VarSet := Make(Nat_as_OT).
Inductive Judgement : Type :=
| judge (v : var) (t : type)
.
Definition ty_ctx := (list Judgement).
Definition disj_vars (s1 s2 : VarSet.t) := VarSet.Empty (VarSet.inter s1 s2).
Often I'd like to make statements like "this var does not appear in the set of vars bound by ty_ctx", and to that end I've set up a bunch of coercions between these types below.
(* Functions to convert between the different types listed above *)
Fixpoint var_to_varset (v : var) : VarSet.t :=
VarSet.singleton v.
Coercion var_to_varset : var >-> VarSet.t.
Fixpoint bound_variables (g : ty_ctx) : VarSet.t :=
match g with
| nil => VarSet.empty
| cons (judge v _) g' =>VarSet.union (VarSet.singleton v) (bound_variables g')
end.
Coercion bound_variables : ty_ctx >-> VarSet.t.
Inductive ctx_join :=
| join_single (g : ty_ctx)
| join_double (g1 g2 : ty_ctx)
(disjoint_proof : disj_vars g1 g2)
.
Fixpoint coerce_ctx_join (dj : ctx_join) : ty_ctx :=
match dj with
| join_single g => g
| join_double g1 g2 _ => g1 ++ g2
end.
Coercion coerce_ctx_join : ctx_join >-> ty_ctx.
Fixpoint coerce_judgement_to_ty_ctx (j : Judgement) : ty_ctx :=
cons j nil.
Coercion coerce_judgement_to_ty_ctx : Judgement >-> ty_ctx.
You'll notice that the definition of ctx_join relies on coercing its arguments from ty_ctx to VarSet.
I've drawn up the conversion hierarchy just to make things clear
The Problem
I'd like to define an inductive type with the following constructor
Inductive expr_has_type : ty_ctx -> nat -> type -> Prop :=
(* General Expressions *)
| ty_var (g : ty_ctx) (x : var) (t : type) (xfree : disj_vars x g)
: expr_has_type (join_double (judge x t) g xfree) x t
.
The problem is that when I do, I get the following error:
Error:
In environment
expr_has_type : ty_ctx -> nat -> type -> Prop
g : ty_ctx
x : var
t : type
xfree : disj_vars x g
The term "xfree" has type "disj_vars x g" while it is expected to have type
"disj_vars (judge x t) g" (cannot unify "VarSet.In a (VarSet.inter (judge x t) g)" and
"VarSet.In a (VarSet.inter x g)").
However, if I change the type of xfree to disj_vars (VarSet.singleton x) g, then the definition works fine! This seems very odd, as disj_vars is defined only on VarSets, and so it seems like x should automatically be converted toVarSet.singleton x since that's how the coercion is set up.
Even weirder is the fact that if I don't set up the coercion from vars to varsets, then Coq correctly complains about applying dis_vars to a var instead of a VarSet. So the coercion is definitely doing something
Can someone explain to me why the first definition fails? Given the coercions I've set up, to me it like all the definitions above should be equivalent
Note
Changing the type of xfree to disj_vars (judge x t) g also fixes the error. This seems odd too, since to be able to apply disj_vars to j := (judge x t), it first needs to be coerced to a ty_ctx via cons j nil, then to a VarSet via bound_variables, which should produce a VarSet containing only x (which is equivalent to VarSet.singleton x?). So this coercion chain seems to go off without a hitch, while the other one fails even though it's simpler
If you use Set Printing Coercions., the error message will be much more informative about the problem:
The term "xfree" has type "disj_vars (var_to_varset x) (bound_variables g)"
while it is expected to have type
"disj_vars (bound_variables (coerce_judgement_to_ty_ctx (judge x t)))
(bound_variables g)"
The problem is that the coercion of x into a VarSet.t is equal to Var.singleton x, while the coercion in judge reduces to VarSet.union (VarSet.singleton x) VarSet.empty. While these two are propositionally equal, they are not judgmentally equal, so as far as Coq is concerned, the term it came up with is ill-typed.

How can I match on a specific value in Coq?

I'm trying to implement a function that simply counts the number of occurrences of some nat in a bag (just a synonym for a list).
This is what I want to do, but it doesn't work:
Require Import Coq.Lists.List.
Import ListNotations.
Definition bag := list nat.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => O
| v :: t => S (count v t)
| _ :: t => count v t
end.
Coq says that the final clause is redundant, i.e., it just treats v as a name for the head instead of the specific v that is passed to the call of count. Is there any way to pattern match on values passed as function arguments? If not, how should I instead write the function?
I got this to work:
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => O
| h :: t => if (beq_nat v h) then S (count v t) else count v t
end.
But I don't like it. I'd rather pattern match if possible.
Pattern matching is a different construction from equality, meant to discriminate data encoded in form of "inductives", as standard in functional programming.
In particular, pattern matching falls short in many cases, such as when you need potentially infinite patterns.
That being said, a more sensible type for count is the one available in the math-comp library:
count : forall T : Type, pred T -> seq T -> nat
Fixpoint count s := if s is x :: s' then a x + count s' else 0.
You can then build your function as count (pred1 x) where pred1 : forall T : eqType, T -> pred T , that is to say, the unary equality predicate for a fixed element of a type with decidable (computable) equality; pred1 x y <-> x = y.
I found in another exercise that it's OK to open up a match clause on the output of a function. In that case, it was "evenb" from "Basics". In this case, try "eqb".
Well, as v doesn't work in the match, I thought that maybe I could ask whether the head of the list was equal to v. And yes, it worked. This is the code:
Fixpoint count (v : nat) (s : bag) : nat :=
match s with
| nil => 0
| x :: t =>
match x =? v with
| true => S ( count v t )
| false => count v t
end
end.