Fixpoint functions in Type Class Instances - typeclass

I am trying to use a fixpoint style function in the context of a type class instance but it doesn't seem to work. Is there something extra I have to do to make this work? For the time being I've used a hack of moving the function outside the type class and explicitly declaring it Fixpoint. This seems awful, however.
Here's the short example:
Inductive cexp : Type :=
| CAnd : cexp -> cexp -> cexp
| COr : cexp -> cexp -> cexp
| CProp : bool -> cexp.
Class Propable ( A : Type ) := { compile : A -> Prop }.
Instance: Propable cexp :=
{ compile c :=
match c with
| CAnd x y => (compile x) /\ (compile y)
| COr x y => (compile x) \/ (compile y)
| CProp _ => False
end
}.
This fails with:
Error: Unable to satisfy the following constraints:
In environment:
c, x, y : cexp
?Propable : "Propable cexp"
What does one have to do to make this work?

You can use fix to do that:
Instance: Propable cexp :=
{ compile := fix compile c :=
match c with
| CAnd x y => (compile x) /\ (compile y)
| COr x y => (compile x) \/ (compile y)
| CProp _ => False
end
}.
Let me illustrate how one can come up with it. Let's take the following piece of code:
Fixpoint silly n :=
match n with
| 0 => 0
| S n => silly n
end.
Fixpoint here is a vernacular command which makes the definition a little bit easier on the eyes, but it conceals what is going on here. It turns out that what Coq actually does is something like this:
Definition silly' :=
fix self n :=
match n with
| 0 => 0
| S n => self n
end.
You can verify it by using Print silly. after the definition.

Related

Coq: usage of `PartialOrder` typeclass

I am trying to define lexicographic ordering on strings over posets, but I'm not completely sure how to use the PartialOrder typeclass.
Require Import List RelationClasses.
Fail Inductive lex_leq {A : Type} `{po : PartialOrder A} : list A -> list A -> Prop :=
| lnil: forall l, lex_leq nil l
| lcons:
forall (hd1 hd2 : A) (tl1 tl2 : list A),
hd1 <= hd2 -> (* error *)
(hd1 = hd2 -> lex_leq tl1 tl2) ->
lex_leq (hd1 :: tl1) (hd2 :: tl2).
Partial output:
The term "hd1" has type "A" while it is expected to have type "nat".
Clearly <= is the wrong notation to use here; I'm wondering how I can obtain an ordering relation from my po instance.
One can bind the names explicitly to make things more obvious. Before we can do this we need to tell Coq not to complain about unbound variables using the Generalizable Variables command:
From Coq Require Import List RelationClasses.
Generalizable Variables A eqA R.
Inductive lex_leq `{PartialOrder A eqA R} : list A -> list A -> Prop :=
| lnil: forall l, lex_leq nil l
| lcons:
forall (hd1 hd2 : A) (tl1 tl2 : list A),
R hd1 hd2 ->
(hd1 = hd2 -> lex_leq tl1 tl2) ->
lex_leq (hd1 :: tl1) (hd2 :: tl2).
You can find more information in the manual (here).

Using TypeClass Instances Within Typeclasses

I am trying to define two instances of a type class, one of which will use the other's instance. However, unless I bind the function's name outside of the second definition Coq is unable to determine it should use the type class instance from bexp (take a look at the comment for dirty hack). Is there a way to avoid this sort of hack in Coq?
Class Compilable ( A : Type ) := { compile : A -> bool }.
Inductive cexp : Type :=
| CAnd : cexp -> cexp -> cexp
| COr : cexp -> cexp -> cexp
| CProp : bexp -> cexp.
Instance: Compilable bexp :=
{ compile :=
fix compile b :=
match b with
(* elided *)
end
}.
Definition compile2 := compile.
Instance: Compilable cexp :=
{ compile :=
fix compile c :=
match c with
| CAnd x y => (compile x) && (compile y)
| COr x y => (compile x) || (compile y)
| CProp e => (compile2 e) (* <-- dirty hack *)
end
}.
This can be fixed if we replace compile with some other name (rec) like so:
Instance: Compilable cexp :=
{ compile :=
fix rec c :=
match c with
| CAnd x y => (rec x) && (rec y)
| COr x y => (rec x) || (rec y)
| CProp e => (compile e)
end
}.
In this comment the OP pointed out that Haskell easily deals with this situation. To understand the reason why Coq does not do it let us take a look at the type of compile:
About compile.
compile : forall A : Type, Compilable A -> A -> bool
Arguments A, Compilable are implicit and maximally inserted
We can see that Coq is more explicit about how typeclasses work. When you call compile e Coq sort of inserts placeholders standing for the implicit arguments like so #compile _ _ e (see these slides, pages 21-25 for more detail). But with fix compile c you shadowed the previous binding, hence the type error.

How to convert propositional formula to DNF in Coq

I have defined my propositional formulas as follows:
Inductive propForm : Set :=
| top : propForm
| bot : propForm
| var : propVar -> propForm
| orp : propForm -> propForm -> propForm
| andp : propForm -> propForm -> propForm.
I am trying to define a function for transforming a propositional formula into one in DNF. For this, I have defined a function which distributes terms using the distributive law:
Fixpoint distribute (f:propForm) : propForm -> propForm :=
fix distribute1 (g:propForm) : propForm :=
match f with
| f1 \/p f2 => match g with
| g1 \/p g2 => distribute1 g1 \/p distribute1 g2
| _ => distribute f1 g \/p distribute f2 g
end
| _ => match g with
| g1 \/p g2 => distribute1 g1 \/p distribute1 g2
| _ => f /\p g
end
end.
This function works fine. However, I still need to define a function which transforms the propositional formula to DNF. The following function would do what I want, however it is not accepted by Coq because the function is not structurally decreasing in f' for the last case. Any hints and tips would be appreciated.
Fixpoint toDNF (f':propForm):propForm :=
match f' with
| top => f'
| bot => f'
| var _ => f'
| f1 \/p f2 => toDNF f1 \/p toDNF f2
| f1 /\p f2 => toDNF (distribute f1 f2)
end.
Your function is a special case of normalizing an expression from a semi-ring. I wrote a post explaining how to do that in the case of arithmetic expressions, using the Ssreflect and MathComp libraries, but I'll include a more direct answer here.
One idea is to use lists of lists to represent formulas in DNF: after all, they are just a conjunction of a list of disjunctions, which are just lists of literals. You can then reuse the list library to write your function:
Module Sol1.
Require Import Coq.Lists.List.
Import ListNotations.
Notation propVar := nat.
Inductive propAtom :=
| top | bot | var :> propVar -> propAtom.
Inductive propForm : Set :=
| atom :> propAtom -> propForm
| orp : propForm -> propForm -> propForm
| andp : propForm -> propForm -> propForm.
Definition dnfForm := list (list propAtom).
Fixpoint andd (f1 f2 : dnfForm) : dnfForm :=
match f1 with
| [] =>
(* false && f2 = false *)
[]
| cf :: f1 =>
(* (cf || f1) && f2 = cf && f2 || f1 && f2 *)
map (app cf) f2 ++ andd f1 f2
end.
Fixpoint toDNF (f : propForm) : dnfForm :=
match f with
| atom a => [[a]]
| orp f1 f2 => toDNF f1 ++ toDNF f2
| andp f1 f2 => andd (toDNF f1) (toDNF f2)
end.
Compute (toDNF (andp (orp 3 4) (orp 1 2))).
End Sol1.
There are two things to note here. First, I factored variables and constants as a separate propAtom type, and I have called distribute andd, because you can think of it as computing the AND of two expressions in DNF.
Here's another solution that is based on your original code. It seems that your distribute function preserves the invariant of being in DNF; that is, if f1 and f2 are in DNF, then so is distribute f1 f2. Thus, you can just flip the order of the calls:
Module Sol2.
Notation propVar := nat.
Inductive propForm : Set :=
| top : propForm
| bot : propForm
| var :> propVar -> propForm
| orp : propForm -> propForm -> propForm
| andp : propForm -> propForm -> propForm.
Fixpoint distribute (f:propForm) : propForm -> propForm :=
fix distribute1 (g:propForm) : propForm :=
match f with
| orp f1 f2 => match g with
| orp g1 g2 => orp (distribute1 g1) (distribute1 g2)
| _ => orp (distribute f1 g) (distribute f2 g)
end
| _ => match g with
| orp g1 g2 => orp (distribute1 g1) (distribute1 g2)
| _ => andp f g
end
end.
Fixpoint toDNF (f':propForm):propForm :=
match f' with
| top => f'
| bot => f'
| var _ => f'
| orp f1 f2 => orp (toDNF f1) (toDNF f2)
| andp f1 f2 => distribute (toDNF f1) (toDNF f2)
end.
Compute (toDNF (andp (orp 3 4) (orp 1 2))).
End Sol2.

Built-in "< > compare" doesn't work with "IComparable<T>"?

I have a Discriminated Union, and I hope to use built in operators like > < compare max for it.
[<CustomComparison>]
type SymbolType =
| A
| B
| C
| D
interface IComparable<SymbolType> with
member x.CompareTo y =
match x, y with
| A, A-> 0
| A, _ -> 1
| _, A-> -1
| _, _ -> 0
I understand I can use IComparable, but then i have to do a null check, what's worse is that I have to cast it like (SymbolType) y which I assume would be time consuming.
You can already use standard comparison operators on the type. The built-in implementation uses the order of declarations of the individual cases, so:
type SymbolType = A | B | C | D
// Behavior of built-in comparison
A < B = true
D <= C = false
max B D = D
This looks very fragile, so maybe it is not the best thing to rely on. If you have cases that do not contain other values, you can use enum instead of discriminated union and define the ordering you wish:
type SymbolType =
| A = 1
| B = 2
| C = 4
| D = 3
// The order is now defined by your code
SymbolType.C < SymbolType.D = false
You can just implement the required methods with thin wrappers:
[<CustomComparison>]
[<CustomEquality>]
type SymbolType =
| A
| B
| C
| D
override x.Equals y =
match y with
| :? SymbolType as t -> (((x :> IComparable<_>).CompareTo) t)=0
| _ -> false
interface IComparable with
member x.CompareTo y =
match y with
| :? SymbolType as t -> ((x :> IComparable<_>).CompareTo) t
| _ -> failwith "bad comparison"
interface IComparable<SymbolType> with
member x.CompareTo y =
match x, y with
| A, A-> 0
| A, _ -> 1
| _, A-> -1
| _, _ -> 0
This way does avoid any duplicate typing.
On CLR, operators are static functions, so you can't define them in an interface. But boxing can also be avoided if your use the interface as a constraint of type parameter of a generic function.
int Compare<T>(T lhs, T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) // no boxing
}
Sorry, I'm not familiar with F#, so I wrote the example in C#.

i think i got infinite loop for this BST

this code i got is from Alexander Battisti about how to make a tree from a list of data:
let data = [4;3;8;7;10;1;9;6;5;0;2]
type Tree<'a> =
| Node of Tree<'a> * 'a * Tree<'a>
| Leaf
let rec insert tree element =
match element,tree with
| x,Leaf -> Node(Leaf,x,Leaf)
| x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
| x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
| _ -> Leaf
let makeTree = List.fold insert Leaf data
then i want to implement this code to my binary search tree code
let rec BinarySearch tree element =
match element,tree with
| x,Leaf -> BinarySearch (Node(Leaf,x,Leaf)) x
| x,Node(l,y,r) when x<=y ->
BinarySearch l y
| x,Node(l,y,r) when x>y ->
BinarySearch r y
| x,Node(l,y,r) when x=y ->
true
| _ -> false
then i use my search code like this:
> BinarySearch makeTree 5;;
and the result is none because it's like i got an infinite looping
can someone help me? if my code is wrong, please help me to correct it, thank you
The solution by Yin is how I would write it too.
Anyway, here is a solution that is closer to your version and (hopefully) explains what went wrong:
let rec BinarySearch tree element =
match element,tree with
| x, Leaf ->
// You originally called 'BinarySearch' here, but that's wrong - if we reach
// the leaf of the tree (on the path from root to leaf) then we know that the
// element is not in the tree so we return false
false
| x, Node(l,y,r) when x<y ->// This needs to be 'x<y', otherwise the clause would be
// matched when 'x=y' and we wouldn't find the element!
BinarySearch l element // Your recursive call was 'BinarySearch l y' but
// that's wrong - you want to search for 'element'
| x, Node(l,y,r) when x>y ->
BinarySearch r element
| x,Node(l,y,r) -> // You can simplify the code by omitting the 'when'
true // clause (because this will only be reached when
// x=y. Then you can omit the last (unreachable) case
let rec BinarySearch tree element =
match tree with
| Leaf -> false
| Node(l, v, r) ->
if v = element then
true
elif v < element then
BinarySearch r element
else
BinarySearch l element
BinarySearch makeTree 5

Resources