Make [StackExp] instance of Expr class - class

I make class Expr for arithmetic operations
class Expr a where
mul :: a -> a -> a
add :: a -> a -> a
lit :: Integer -> a
i want to "parse" something like this: mul ( add (lit 3) (lit 2)) (lit 4) = (3+2)*4
and i have data type:
data StackExp = PushI Integer
| PushB Bool
| Add
| Mul
| And
| Or
deriving Show
and
type Program = [StackExp] --i use this type for function of stack calculator later
my task is: i need to make instance of Expr for type Program
more concrete - i want to make this transformation:
mul ( add (lit 3) (lit 2)) (lit 4) ->>> [PushI 2, PushI 3, Add, PushI 4, Mul]
i have problems because i receive [[StackExp]] at the output of my instance declaration.
my try:
instance Expr Program where
lit n = (PushI n):[]
add exp1 exp2 = exp1:(exp2:[Add])
mul exp1 exp2 = exp1:(exp2:[Mul])
i don't know how to concatenate all sub-expressions into list
---------------- compiler error looks like this------------------------
Couldn't match type `[StackExp]' with `StackExp'
Expected type: StackExp
Actual type: Program
..........

So, what you basically want to do is you want to compile from the abstract syntax of your expression language (the type class Expr) to code for a simple stack machine (a list of elements of type StackExpr).
One problem that you immediately run into then is that, in just Haskell 98 or Haskell 2010, you cannot declare [StackExpr] an instance of a class. For example, GHC will complain with
Illegal instance declaration for `Expr [StackExp]'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Expr [StackExp]'
To work your way around this, you could define Program as a type isomorphism (rather than as a mere type synonym as you have now):
newtype Program = P [StackExp] deriving Show
and then make Program an instance of the class Expr. (Alternatively, you could enable FlexibleInstances as suggested by the error message above.)
Now we can write the required instance declaration:
instance Expr Program where
mul (P x) (P y) = P (x ++ y ++ [Mul])
add (P x) (P y) = P (x ++ y ++ [Add])
lit n = P [PushI n]
That is, for multiplication and addition, we first compile the operands and then produce, respectively, the Mul or Add instruction; for literals we produce the corresponding push instruction.
With this declaration, we get, for your example:
> mul (add (lit 3) (lit 2)) (lit 4) :: Program
P [PushI 3,PushI 2,Add,PushI 4,Mul]
(Not quite as in your example. You swap the order of the operands to Add. As addition is commutative, I will assume that this version is acceptable as well.)
Of course it is more fun to also write a small evaluator for stack programs:
eval :: Program -> [Integer]
eval (P es) = go es []
where
go [] s = s
go (PushI n : es) s = go es (n : s)
go (Add : es) (m : n : s) = go es ((m + n) : s)
go (Mul : es) (m : n : s) = go es ((m * n) : s)
(Note that I am ignoring instructions that deal with Booleans here as you only seem to deal with integer expressions anyway.)
Now we have, for your example,
> eval (mul (add (lit 3) (lit 2)) (lit 4))
[20]
which seems about right.

Related

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 do I code algebraic cpos as an Isabelle locale

I am trying to prove the known fact that there is a standard way to build an algebriac_cpo from a partial_order. My problem is I keep getting the error
Type unification failed: No type arity set :: partial_order
and I can not understand what this means.
I think I have tracked down my problem to the definition of cpo. The definition works and I have proven various results for it but the working interpretation of a partial_order fails with cpo.
theory LocaleProblem imports "HOL-Lattice.Bounds"
begin
definition directed:: "'a::partial_order set ⇒ bool" where
" directed a ≡
¬a={} ∧ ( ∀ a1 a2. a1∈a∧ a2∈a ⟶ (∃ ub . (is_Sup {a1,a2} ub))) "
class cpo = partial_order +
fixes bot :: "'a::partial_order" ("⊥")
assumes bottom: " ∀ x::'a. ⊥ ⊑ x "
assumes dlub: "directed (d::'a::partial_order set) ⟶ (∃ lub . is_Inf d lub) "
print_locale cpo
interpretation "idl" : partial_order
"(⊆)::( ('b set) ⇒ ('b set) ⇒ bool) "
by (unfold_locales , auto) (* works *)
interpretation "idl" : cpo
"(⊆)::( ('b set) ⇒ ('b set) ⇒ bool) "
"{}" (* gives error
Type unification failed: No type arity set :: partial_order
Failed to meet type constraint:
Term: (⊆) :: 'b set ⇒ 'b set ⇒ bool
Type: ??'a ⇒ ??'a ⇒ bool *)
Any help much appreciated. david
You offered two solutions.
Following the work of Hennessy in Algebraic Theory of Processes" I am trying to prove (where I(A) are the Ideal which are sets) "If a is_a partial_order then I(A) is an algebraic_cpo" I will then want to apply the result to a number of semantics, give as sets. Dose your comment mean that the second solution is not a good idea?
Initially I had a proven lemma that started
lemma directed_ran: "directed (d::('a::partial_order×'b::partial_order) set) ⟹ directed (Range d)"
proof (unfold directed_def)
With the First solution started well:
context partial_order begin (* type 'a is now a partial_order *)
definition
is_Sup :: "'a set ⇒ 'a ⇒ bool" where
"is_Sup A sup = ((∀x ∈ A. x ⊑ sup) ∧ (∀z. (∀x ∈ A. x ⊑ z) ⟶ sup ⊑ z))"
definition directed:: "'a set ⇒ bool" where
" directed a ≡
¬a={} ∧ ( ∀ a1 a2. a1∈a∧ a2∈a ⟶ (∃ ub . (is_Sup {a1,a2} ub))) "
lemma directed_ran: "directed (d::('c::partial_order×'b::partial_order) set) ⟹ directed (Range d)"
proof - assume a:"directed d"
from a local.directed_def[of "d"] (* Fail with message below *)
show "directed (Range d)"
Alas the working lemma now fails: I rewrote
proof (unfold local.directed_def)
so I explored and found that although the fact local.directed_def exists is can not be unified
Failed to meet type constraint:
Term: d :: ('c × 'b) set
Type: 'a set
I changed the type successfully in the lemma statement but now can find no way to unfold the definition in the proof. Is there some way to do this?
Second solution again starts well:
instantiation set:: (type) partial_order
begin
definition setpoDef: "a⊑(b:: 'a set) = subset_eq a b"
instance proof
fix x::"'a set" show " x ⊑ x" by (auto simp: setpoDef)
fix x y z::"'a set" show "x ⊑ y ⟹ y ⊑ z ⟹ x ⊑ z" by(auto simp: setpoDef)
fix x y::"'a set" show "x ⊑ y ⟹ y ⊑ x ⟹ x = y" by (auto simp: setpoDef)
qed
end
but next step fails
instance proof
fix d show "directed d ⟶ (∃lub. is_Sup d (lub::'a set))"
proof assume "directed d " with directed_def[of "d"] show "∃lub. is_Sup d lub"
by (metis Sup_least Sup_upper is_SupI setpoDef)
qed
next
from class.cpo_axioms_def[of "bot"] show "∀x . ⊥ ⊑ x " (* Fails *)
qed
end
the first subgoal is proven but show "∀x . ⊥ ⊑ x " although cut an paste from the subgaol in the output does not match the subgoal. Normally at this point is need to add type constraints. But I cannot find any that work.
Do you know what is going wrong?
Do you know if I can force the Output to reveal the type information in the sugoal.
The interpretation command acts on the locale that a type class definition implicitly declares. In particular, it does not register the type constructor as an instance of the type class. That's what the command instantiation is good for. Therefore, in the second interpretation, Isabelle complains about set not having been registered as a instance of partial_order.
Since directed only needs the ordering for one type instance (namely 'a), I recommend to move the definition of directed into the locale context of the partial_order type class and remove the sort constraint on 'a:
context partial_order begin
definition directed:: "'a set ⇒ bool" where
"directed a ≡ ¬a={} ∧ ( ∀ a1 a2. a1∈a∧ a2∈a ⟶ (∃ ub . (is_Sup {a1,a2} ub))) "
end
(This only works if is_Sup is also defined in the locale context. If not, I recommend to replace the is_Sup condition with a1 <= ub and a2 <= ub.)
Then, you don't need to constrain 'a in the cpo type class definition, either:
class cpo = partial_order +
fixes bot :: "'a" ("⊥")
assumes bottom: " ∀ x::'a. ⊥ ⊑ x "
assumes dlub: "directed (d::'a set) ⟶ (∃ lub . is_Inf d lub)"
And consequently, your interpretation should not fail due to sort constraints.
Alternatively, you could declare set as an instance of partial_order instead of interpreting the type class. The advantage is that you can then also use constants and theorems that need partial_order as a sort constraint, i.e., that have not been defined or proven inside the locale context of partial_order. The disadvantage is that you'd have to define the type class operation inside the instantiation block. So you can't just say that the subset relation should be used; this has to be a new constant. Depending on what you intend to do with the instantiation, this might not matter or be very annoying.

Dependent Typing style Equality Proofs in Scala

Is it possible to implement an equality proof in Scala?
In the book Type Driven Development with Idris it gives an example of how the equality proof type could be defined.
data (=): a -> b -> Type where
Refl : x = x
My first instinct to convert this to Scala is something like this.
sealed trait EqualityProof[A, B]
final case class EqualityProofToken[T](value: T) extends EqualityProof[value.type, value.type]
However this requires I prove to the compiler that the two objects I want to compare are the same exact instance. Ideally this would work for equal objects that are different instances, though that may be asking too much. Is this just a limitation that can't be avoided due to Scala allowing mutable data? Is there any way to implement this properly? If not is there a workaround other than using asInstanceOf to lie to the compiler (or a way to limit the use of asInstanceOf)?
Update: It seems there is some confusion about the definition of the problem so I'm adding a more complete Idris example.
data EqNat : (num1 : Nat) -> (num2 : Nat) -> Type where
Same : (num : Nat) -> EqNat num num
sameS : (k : Nat) -> (j : Nat) -> (eq : EqNat k j) -> EqNat (S k) (S j)
sameS k k (Same k) = Same (S k)
checkEqNat : (num1 : Nat) -> (num2 : Nat) -> Maybe (EqNat num1 num2)
checkEqNat Z Z = Just (Same 0)
checkEqNat Z (S k) = Nothing
checkEqNat (S k) Z = Nothing
checkEqNat (S k) (S j) = case checkEqNat k j of
Nothing => Nothing
Just eq => Just (sameS _ _ eq)
At this point the EqNat instance can be used to perform operations that require equal values such as zipping to lists of lengths that have been proven equal.
A simple translation from Idris is quite straightforward, you just use an implicit to provide the compile-time proof:
sealed trait Equality[A, B]
case class Refl[A]() extends Equality[A, A]
case object Equality {
implicit def refl[B]: Equality[B, B] = Refl[B]()
}
It's placed in the companion object, so it will be always in scope when you're requiring an implicit of the Equality type.
You can find a more involved definition of such equality-type in the ohnosequences/cosas library together with some tests/examples. (disclaimer: I'm one of maintainers)

Is there a way to derive Num class functions in own data type in Haskell?

Let's say I have a type declaration:
data MyType = N Double | C Char | Placeholder
I want to be able to treat MyType as a Double whenever it's possible, with all the Num, Real, Fractional functions resulting in N (normal result) for arguments wrapped in the N constructor, and Placeholder for other arguments
> (N 5.0) + (N 6.0)
N 11.0
> (N 5.0) + (C 'a')
Placeholder
Is there a way to do this other than simply defining this class as an instance of those classes in a manner similar to:
instance Num MyType where
(+) (N d1) (N d2) = N (d1+d2)
(+) _ _ = Placeholder
...
(which seems counter-productive)?
There is no generic deriving available in standard Haskell: currently, deriving is only available as defined by the compiler for specific Prelude typeclasses: Read, Show, Eq, Ord, Enum, and Bounded.
The Glasgow Haskell Compiler (GHC) apparently has extensions that support generic deriving. However, I don't know if it would actually save you any work to try and use them: how many typeclasses do you need to derive a Num instance from? And, are you sure that you can define an automatic scheme for deriving Num that will always do what you want?
As noted in the comments, you need to describe what your Num instance will do in any case. And describing and debugging a general scheme is certain to be more work than describing a particular one.
No, you can't do this automatically, but I think what leftaroundabout could have been getting at is that you can use Applicative operations to help you.
data MyType n = N n | C Char | Placeholder deriving (Show, Eq, Functor)
instance Applicative MyType where
pure = N
(<*>) = ap
instance Monad MyType where
N n >>= f = f n
C c >>= _ = C c
Placeholder >>= _ = Placeholder
Now you can write
instance Num n => Num (MyType n) where
x + y = (+) <$> x <*> y
abs = fmap abs
...

Generating code from locales without interpretation

I would love to generate code from locale definitions directly, without interpretation. Example:
(* A locale, from the code point of view, similar to a class *)
locale MyTest =
fixes L :: "string list"
assumes distinctL: "distinct L"
begin
definition isInL :: "string => bool" where
"isInL s = (s ∈ set L)"
end
The assumptions to instantiate MyTest are executable and I can generate code for them
definition "can_instance_MyTest L = distinct L"
lemma "can_instance_MyTest L = MyTest L"
by(simp add: MyTest_def can_instance_MyTest_def)
export_code can_instance_MyTest in Scala file -
I can define a function to execute the isInL definition for arbitrary MyTest.
definition code_isInL :: "string list ⇒ string ⇒ bool option" where
"code_isInL L s = (if can_instance_MyTest L then Some (MyTest.isInL L s) else None)"
lemma "code_isInL L s = Some b ⟷ MyTest L ∧ MyTest.isInL L s = b"
by(simp add: code_isInL_def MyTest_def can_instance_MyTest_def)
However, code export fails:
export_code code_isInL in Scala file -
No code equations for MyTest.isInL
Why do I want to do such a thing?
I'm working with a locale in the context of a valid_graph similar to e.g. here but finite. Testing that a graph is valid is easy. Now I want to export the code of my graph algorithms into Scala. Of course, the code should run on arbitrary valid graphs.
I'm thinking of the Scala analogy similar to something like this:
class MyTest(L: List[String]) {
require(L.distinct)
def isInL(s: String): Bool = L contains s
}
One way to solve this is datatype refinement using invariants (see isabelle doc codegen section 3.3). Thereby the validity assumption (distinct L, in your case) can be moved into a new type. Consider the following example:
typedef 'a dlist = "{xs::'a list. distinct xs}"
morphisms undlist dlist
proof
show "[] ∈ ?dlist" by auto
qed
This defines a new type whose elements are all lists with distinct elements. We have to explicitly set up this new type for the code generator.
lemma [code abstype]: "dlist (undlist d) = d"
by (fact undlist_inverse)
Then, in the locale we have the assumption "for free" (since every element of the new type guarantees it; however, at some point we have to lift a basic set of operations from lists with distinct element to 'a dlists).
locale MyTest =
fixes L :: "string dlist"
begin
definition isInL :: "string => bool" where
"isInL s = (s ∈ set (undlist L))"
end
At this point, we are able to give (unconditional) equations to the code generator.
lemma [code]: "MyTest.isInL L s ⟷ s ∈ set (undlist L)"
by (fact MyTest.isInL_def)
export_code MyTest.isInL in Haskell file -
I found a method, thanks to chris' tips.
Define a function to test the prerequisites/assumptions to instantiate a MyTest
definition "can_instance_MyTest L = distinct L"
The command term MyTest reveals that MyTest is of type string list => bool,
this means that MyTest is a predicate that takes a parameter and tests if this parameter fulfills MyTest's assumptions.
We introduce a code equation ([code]) that replaces MyTest with the executable instance tester.
The code generator can now produce code for occurrences of e.g., MyTest [a,b,c]
lemma [code]: "MyTest = can_instance_MyTest"
by(simp add:fun_eq_iff MyTest_def can_instance_MyTest_def)
export_code MyTest in Scala file -
We yield (I replaced List[Char] with String for readability):
def can_instance_MyTest[A : HOL.equal](l: List[A]): Boolean =
Lista.distinct[A](l)
def myTest: (List[String]) => Boolean =
(a: List[String]) => can_instance_MyTest[String](a)
More readable pseudo-code:
def myTest(l: List[String]): Boolean = l.isDistinct
Now we need executable code for isInL. We utilize the predefined constant undefined. This code throws an exception if L is not distinct.
definition code_isInL :: "string list ⇒ string ⇒ bool" where
"code_isInL L s = (if can_instance_MyTest L then s ∈ set L else undefined)"
export_code code_isInL in Scala file -
We yield:
def code_isInL(l: List[String], s:String): Boolean =
(if (can_instance_MyTest[String](l)) Lista.member[String](l, s)
else sys.error("undefined"))*)
We just need to show that the code_isInL is correct:
lemma "b ≠ undefined ⟹ code_isInL L s = b ⟷ MyTest L ∧ MyTest.isInL L s = b"
by(simp add: code_isInL_def MyTest_def can_instance_MyTest_def MyTest.isInL_def)
(* Unfortunately, the other direction does not hold. The price of undefined. *)
lemma "¬ MyTest L ⟹ code_isInL L s = undefined"
by(simp add: code_isInL_def can_instance_MyTest_def MyTest_def)