Lambda calculus implementation using CBV small step operational semantics - functional-programming

I'm trying to implement an interpreter for the lambda calculus that has constant intergers and supports the addition operation. The interpreter should use the call-by-value small-step operational semantics. So I've implemented a step that should be able to reduce a lambda term by one step. However, the stepper is losing the surrounding program of the reduced subterm when reduced.
This is my implementation in F#:
type Exp =
| Cst of int
| Var of string
| Abs of string * Exp
| App of Exp * Exp
| Arith of Oper * Exp * Exp
and Oper =
Plus
and the stepper looks like this:
let rec step (exp : Exp) (env : Map<string, Exp>) : Exp =
match exp with
| Cst _ | Abs(_) -> exp
| Var x ->
match Map.tryFind x env with
| Some v -> v
| None -> failwith "Unbound variable"
| App(e1, e2) ->
match step e1 env with
| Abs(x, e) ->
let newEnv = Map.add x (step e2 env) env
step e newEnv
| e1' -> failwithf "%A is not a lambda abstraction" e1'
| Arith(Plus, Cst a, Cst b) -> Cst (a + b)
| Arith(Plus, e1, Cst b) -> Arith(Plus, step e1 env, Cst b)
| Arith(Plus, Cst a, e2) -> Arith(Plus, Cst a, step e2 env)
| Arith(Plus, a, b) -> Arith(Plus, step a env, step b env)
So, given the following example of a program (\x.(\y.y x) 21 + 21) \x.x + 1
App
(Abs
("x", App (Abs ("y", App (Var "y", Var "x")), Arith (Plus, Cst 21, Cst 21))),
Abs ("x", Arith (Plus, Var "x", Cst 1)))
I expect the step function to only reduce the 21 + 21 while keeping the rest of the program i.e. I expect the following output after one step (\x.(\y.y x) 42) \x.x + 1. However, I'm not able to retain the surrounding code around the Cst 42. How should I modify the program such that it reduction only steps once while maintaining the rest of the program?

I think there are two things that you should do differently if you want to implement standard small-step CBV lambda calculus.
First, you want to always perform just one step. This means that you should always call step recursively only once. For example, you have Arith(Plus, step a env, step b env) - but this means that if you have an expression representing (1+2)+(2+3), you will reduce this in "one step" to 3+5 but this is really two steps in one.
Second, I don't think your way of handling variables will work. If you have (\x.x+2) 1, this should reduce to 1+2 using variable substitution. You could reduce this to x+2 and remember the assignment x=1 on the side, but then your function would need to work on expression alongside with variable assignment Exp * Map<string, Exp> -> Exp * Map<string, Exp>. It is easier to use normal substitution, at least for the start.
So, I would first define subst x repl exp which substitutes all free occurences of x in the expression exp with repl:
let rec subst (n : string) (repl : Exp) (exp : Exp) =
match exp with
| Var x when x = n -> repl
| Cst _ | Var _ -> exp
| Abs(x, _) when x = n -> exp
| Abs(x, b) -> Abs(x, subst n repl b)
| App(e1, e2) -> App(subst n repl e1, subst n repl e2)
| Arith(op, e1, e2) -> Arith(op, subst n repl e1, subst n repl e2)
Now you can implement your step function.
let rec step (exp : Exp) =
match exp with
// Values - do nothing & return
| Cst _ | Abs _ -> exp
// There should be no variables, because we substituted them
| Var x -> failwith "Unbound variable"
// App #1 - e1 is function, e2 is a value, apply
| App(Abs(x, e1), (Cst _ | Abs _)) -> subst x e2 e1
// App #2 - e1 is not a value, reduce that first
| App(e1, e2) -> App(step e1, e2)
// App #3 - e1 is value, but e2 not, reduce that
| App(Abs(x,e1), e2) -> App(Abs(x,e1), step e2)
// Similar to App - if e1 or e2 is not value, reduce e1 then e2
| Arith(Plus, Cst a, Cst b) -> Cst (a + b)
| Arith(Plus, Cst a, e2) -> Arith(Plus, Cst a, step e2)
| Arith(Plus, a, b) -> Arith(Plus, step a, b)
Using your example:
App
(Abs
("x", App (Abs ("y", App (Var "y", Var "x")), Arith (Plus, Cst 21, Cst 21))),
Abs ("x", Arith (Plus, Var "x", Cst 1)))
|> step
|> step
|> step
|> step
I get:
App (Cst 42, Abs ("x", Arith (Plus, Var "x", Cst 1)))
And if I'm correctly making sense of your example, this is correct - because now you are trying to treat a number as a function, which gets stuck.

Related

Splitting a premise with conjunction conclusion in Coq

I often have to do "induction loading" to prove goals in Coq, where I prove multiple things simultaneously by induction.
The problem is, I often end up with Inductive Hypotheses of the following form:
forall a1 ... an,
Premise1 -> Premise2 -> ... Premisek ->
Conclusion1 /\ Conclusion2 /\ ... Conclusion_m
This is fine, but tactics like eauto really don't know how to handle things like this, so it kills automation most of the time.
What I'm wondering is, is there a way to automatically break such a premise into m different premises, i.e.
forall a1 ... an,
Premise1 -> Premise2 -> ... Premisek ->
Conclusion1
...
forall a1 ... an,
Premise1 -> Premise2 -> ... Premise_k ->
Conclusion_m
The main problem I'm running into is that I don't know how to match with an arbitrary length chain of arrows in LTac. I could hard-code up to a certain length, but I'm hoping there's a better way.
Additionally, if it were possible to do the dual (i.e. split on all combinations of disjunctions in Premise1 .. Premise_k) that would also be useful.
I am not an expert of Ltac, but I gave it a try and came up with the following tactic.
Ltac decomp H :=
try match type of H with
context c [?A /\ ?B] =>
let H' := fresh H in
let Pa := context c[A] in
assert (H' : Pa) by (apply H);
let H'' := fresh H in
let Pb := context c[B] in
assert (H'' : Pb) by (apply H);
clear H;
rename H' into H;
rename H'' into H';
decomp H'
end.
Tactic Notation "decomp_hyp" hyp(H) := decomp H.
decomp H searches occurrences of conjunctions in H, then decomposes it into H' and H'', clean the state and calls itself recursively.
On a trivial example, this seems to work.
Perhaps something like this (minus the debug printouts)?
Ltac foo :=
match goal with
| |- forall q, ?X =>
let x := fresh in intros x; idtac x q ; (try foo); generalize x as q; clear x
| |- ?X -> _ =>
let x := fresh in intros x; idtac x ; (try foo); generalize x; clear x
| |- _ /\ _ => repeat split
end; idtac "done".
Goal forall {T} (a1 a2 a3:T) P1 P2 P3 Q1 Q2 Q3, P1 a1 -> P2 a2 -> P3 a3 -> Q1 /\ Q2 /\ Q3.
foo.
This leaves you with the goals
3 subgoals (ID 253)
============================
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type) (Q1 : Prop),
Prop -> Prop -> P1 a1 -> P2 a2 -> P3 a3 -> Q1
subgoal 2 (ID 254) is:
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type),
Prop -> forall Q2 : Prop, Prop -> P1 a1 -> P2 a2 -> P3 a3 -> Q2
subgoal 3 (ID 255) is:
forall (T : Type) (a1 a2 a3 : T) (P1 P2 P3 : T -> Type),
Prop -> Prop -> forall Q3 : Prop, P1 a1 -> P2 a2 -> P3 a3 -> Q3

OCaml function to evaluate addition and subtraction

I'm currently trying to write an OCaml function that will evaluate expressions and return a Boolean value. I've tried to do research online, and the closest answer that I could find is this one. However, I'm still having trouble which led me to ask my own question.
Here's the basic code:
type equation =
| True
| False
| Equal of exp * exp
and exp =
| Val of int
| Add of exp * exp
| Sub of exp * exp
let rec eval : equation -> bool
= fun f ->
match f with
| True -> true
| False -> false
| Equal (x, y) -> match (x, y) with
| (Val a, Val b) -> if (x = y) then true else false
| ((Add (Val a, Val b), c) -> eval (Equal (Val (a + b), c))
The program is incomplete, and the recursive call to eval in the last line is where I got stuck. A specific input example that I've thought of is:
eval (Equal (Add (Add (Val 1, Val 2), Val 3), Val 6))
This should evaluate to true, since the two Add's add up to 6, and Equal compares Val 6 with Val 6. The trouble that I'm experiencing is how to recursively call the function to evaluate the second Add inside the expression, so that Add (Val 2, Val 2) first evaluates to Val 3, then the first Add adds Val 3 with Val 3. The program that I've written right now only evaluates one of the two Add's.
Is there anything that I should be thinking of or keeping in mind? Any feedback is welcome. Thank you.
As #Amadan mentioned, it's easier to define a function that would first evaluate expression to an int eval_exp: exp -> int. Then you can just evaluate both expressions in the tuple Equal(e1, e2) and compare them (eval: equation -> bool).
You also do not need values True and False in type equation, because you can just return bool from function without pattern-matching. Note that you could need True and False if you passed those, for some reason, again to eval function.
type equation =
Equal of exp * exp
and exp =
| Val of int
| Add of exp * exp
| Sub of exp * exp
let rec eval (e: equation) : bool =
let rec eval_exp e =
match e with
| Val i -> i
| Add (e1, e2) -> (eval_exp e1) + (eval_exp e2)
| Sub (e1, e2) -> (eval_exp e1) - (eval_exp e2)
in
match e with
| Equal (e1, e2) ->
if (eval_exp e1) = (eval_exp e2)
then true
else false

OCaml error with types

I have the following error from OCaml and I don't understand why. I'm trying to define an interpreter in OCaml. I have some types and functions to evaluate these types. I paste the relevant code.
I have these types:
type ide = string
type exp = Eint of int
| Ebool of bool
| Var of ide
| Prod of exp * exp
| Sum of exp * exp
| Diff of exp * exp
| Eq of exp * exp
| Minus of exp
| Iszero of exp
| Or of exp * exp
| And of exp * exp
| Not of exp
| Ifthenelse of exp * exp * exp
| Let of ide * exp * exp
| Fun of ide list * exp
| Funval of exp * exp env
| Appl of exp * exp list
| Dot of ide * field_name
|Field of ide * exp
| Record of ide * exp list;;
type 'a env = Env of (ide * 'a) list;;
I have a function eval used to eval exp. It works correctly.
let rec eval ((e: exp), (r: exp env)) =
match e with
| Eint(n) -> Eint(n)
| Ebool(b) -> Ebool(b)
| Var(i) -> lookup r i
| Iszero(a) -> iszero(eval(a, r))
| Eq(a, b) -> equ(eval(a, r),eval(b, r))
| Prod(a, b) -> mult(eval(a, r), eval(b, r))
| Sum(a, b) -> plus(eval(a, r), eval(b, r))
| Diff(a, b) -> diff(eval(a, r), eval(b, r))
| Minus(a) -> minus(eval(a, r))
| And(a, b) -> et(eval(a, r), eval(b, r))
| Or(a, b) -> vel(eval(a, r), eval(b, r))
| Not(a) -> non(eval(a, r))
| Ifthenelse(a, b, c) -> let g = eval(a, r) in
if typecheck("bool", g) then
(if g = Ebool(true) then eval(b, r) else eval(c, r))
else failwith ("nonboolean guard")
| Let(i, e1, e2) ->
eval(e2, bind (r, i, eval(e1, r)))
| Fun(x, a) -> Funval(e, r)
| Appl(e1, e2) -> match eval(e1, r) with
| Funval(Fun(x, a), r1) ->
eval(a, bind_list r1 x e2)
| _ -> failwith("no funct in apply")
let eval_field (field:exp) (r: exp env)= match field with
| Field (id, e) -> Field (id, (eval e r))
| _ -> failwith ("Not a Field");;
And finally I have a function to evaluate fields of record:
let eval_field (field:exp) (r: exp env)= match field with
| Field (id, e) -> Field (id, (eval e r))
| _ -> failwith ("Not a Field");;
The problem is with eval_field: OCaml signals me ths error:
Characters 22-24:
let f1 = Field ("f1", e1);;
^^
Error: This expression has type exp/1542
but an expression was expected of type exp/2350
What could be wrong?
Thank you very much for your help.
The compiler is trying to tell you that you have two different types named exp and that you have one of them where the other is expected.
I only see one definition for the type exp in this code. I suspect your environment isn't clean. You might try loading the code up in a new OCaml interpreter. Or perhaps the problem is with some code you're not showing.
Here's a session showing how the error is produced:
$ ocaml
OCaml version 4.02.1
# type abc = A | B | C;;
type abc = A | B | C
# let f (x: abc) = x = A;;
val f : abc -> bool = <fun>
# type abc = A | B | C;;
type abc = A | B | C
# f (C: abc);;
Error: This expression has type abc/1024
but an expression was expected of type abc/1018
My guess is that you have a function (like f here) that was defined using an old definition of your exp type. But you're calling it with a value from the new definition of the type (as here).

logical calculation of Integer interval

what are the rules to calculate logical op. (AND OR XOR) of two integer intervals ?
Given two intervals [a,b] [c,d] i want to calculate [a,b] xor [c,d]
I assume the result to be multiple ranges
I looked at filib++ and read WIKI but found just Arithmetic op. support
Can anyone educate me
You can find an implementation of “bitwise and”, “bitwise xor” and “bitwise or” between intervals in the latest version of Frama-C, in file src/ai/ival.ml. In fact these functions operate on values of type Ival.t, which represent either a small set of integer values, an interval with congruence information or a floating-point interval. You will only be interested in the case Top _, Top _ (which corresponds to the integer intervals with congruence information). The function compute the result as an Ival.t, possibly over-approximated, but which contains all the values x op y with x in the first interval and y in the second interval.
As the comment says, the algorithm for pos_max_land is optimal for precision but does not have the best complexity with respect to the number of bits of the integers. I only understood this after I was finished with writing the function, and the width of an integer does not go beyond 64 for this usecase, so I didn't bother writing the faster version.
The file src/ai/ival.ml is licensed under the LGPL 2.1. If you do something cool with it, I would be happy to hear about it.
(* [different_bits min max] returns an overapproximation of the mask
of the bits that can be different for different numbers
in the interval [min]..[max] *)
let different_bits min max =
let x = Int.logxor min max in
next_pred_power_of_two x
(* [pos_max_land min1 max1 min2 max2] computes an upper bound for
[x1 land x2] where [x1] is in [min1]..[max1] and [x2] is in [min2]..[max2].
Precondition : [min1], [max1], [min2], [max2] must all have the
same sign.
Note: the algorithm below is optimal for the problem as stated.
It is possible to compute this optimal solution faster but it does not
seem worth the time necessary to think about it as long as integers
are at most 64-bit. *)
let pos_max_land min1 max1 min2 max2 =
let x1 = different_bits min1 max1 in
let x2 = different_bits min2 max2 in
(* Format.printf "pos_max_land %a %a -> %a | %a %a -> %a#."
Int.pretty min1 Int.pretty max1 Int.pretty x1
Int.pretty min2 Int.pretty max2 Int.pretty x2; *)
let fold_maxs max1 p f acc =
let rec aux p acc =
let p = Int.shift_right p Int.one in
if Int.is_zero p
then f max1 acc
else if Int.is_zero (Int.logand p max1)
then aux p acc
else
let c = Int.logor (Int.sub max1 p) (Int.pred p) in
aux p (f c acc)
in aux p acc
in
let sx1 = Int.succ x1 in
let n1 = fold_maxs max1 sx1 (fun _ y -> succ y) 0 in
let maxs1 = Array.make n1 sx1 in
let _ = fold_maxs max1 sx1 (fun x i -> Array.set maxs1 i x; succ i) 0 in
fold_maxs max2 (Int.succ x2)
(fun max2 acc ->
Array.fold_left
(fun acc max1 -> Int.max (Int.logand max1 max2) acc)
acc
maxs1)
(Int.logand max1 max2)
let bitwise_or v1 v2 =
if is_bottom v1 || is_bottom v2
then bottom
else
match v1, v2 with
Float _, _ | _, Float _ -> top
| Set s1, Set s2 ->
apply2_v Int.logor s1 s2
| Set s, v | v, Set s when Array.length s = 1 && Int.is_zero s.(0) -> v
| Top _, _ | _, Top _ ->
( match min_and_max v1 with
Some mn1, Some mx1 when Int.ge mn1 Int.zero ->
( match min_and_max v2 with
Some mn2, Some mx2 when Int.ge mn2 Int.zero ->
let new_max = next_pred_power_of_two (Int.logor mx1 mx2) in
let new_min = Int.max mn1 mn2 in (* Or can only add bits *)
inject_range (Some new_min) (Some new_max)
| _ -> top )
| _ -> top )
let bitwise_xor v1 v2 =
if is_bottom v1 || is_bottom v2
then bottom
else
match v1, v2 with
| Float _, _ | _, Float _ -> top
| Set s1, Set s2 -> apply2_v Int.logxor s1 s2
| Top _, _ | _, Top _ ->
(match min_and_max v1 with
| Some mn1, Some mx1 when Int.ge mn1 Int.zero ->
(match min_and_max v2 with
| Some mn2, Some mx2 when Int.ge mn2 Int.zero ->
let new_max = next_pred_power_of_two (Int.logor mx1 mx2) in
let new_min = Int.zero in
inject_range (Some new_min) (Some new_max)
| _ -> top )
| _ -> top )

Pattern-matching returning a string representation of math expression

I have to write a function dump which takes an expression
type expression =
| Int of int
| Float of float
| Add of expression * expression
| Sub of expression * expression
| Mult of expression * expression
| Div of expression * expression
;;
and returns a string representation of it.
For example:
dump (Add (Int 1, Int 2));;
dump (Mult (Int 5, Add(Int 2, Int 3)), Int 1)
should return respectively
- : string = "1+2"
- : string = "5*(2+3)-1"
I've written something like this:
let rec dump e = match e with
| Int a -> string_of_int a
| Float a -> string_of_float a
| Add (e1,e2) -> "(" ^ (dump e1) ^ "+" ^ (dump e2) ^ ")"
| Sub (e1,e2) -> "(" ^ (dump e1) ^ "-" ^ (dump e2) ^ ")"
| Mult (e1,e2) -> (dump e1) ^ "*" ^ (dump e2)
| Div (e1,e2) -> (dump e1) ^ "/" ^ (dump e2)
;;
and returned expressions are correct, but still not optimal.
(for Add (Int 1, Int 2)) it is (1+2) and should be 1+2 ). How can I fix this?
(without nested pattern matching which isn't a good idea)
Let's think about when you need parens:
First of all always wrapping parens around certain operations is the wrong approach. Whether a term needs to be parenthesized or not does not only depend on which operator is used in the term, but also which operator the term is an operand to.
E.g. when 1+2 and 3+4 are operands to +, it should be 1+2+3+4 - no parens. However if the operator is *, it needs to be (1+2) * (3+4).
So for which combinations of operators do we need parens?
The operands to + never need to be parenthesized. If the operands are products or quotients, they have higher precedence anyway, and if the operands are differences, you need no parens because x + (y - z) = x + y -z.
With - it's a bit different. * and / still don't need to be parenthesized because they have higher precedence, but + and - do iff they're in the second operand because x + y - z = (x + y) - z, but x - y + z != x - (y + z).
With Mult both operands need to be parenthesized if they're Add or Sub, but not if they're Mult or Div.
With Div the first operand needs to be parenthesized if it's Add or Sub and the second always needs to be parenthesized (unless it's an Int or Float, of course).
First, define a list of priority levels for your operators:
module Prio = struct
let div = 4
let mul = 3
let sub = 2
let add = 1
end
An useful construct is "wrap in brackets if this condition is true" :
let wrap_if c str = if c then "("^str^")" else str
Finally, define an auxiliary printing function which is provided with a "priority" argument meaning "by the way, you're wrapped in an expression which has priority X, so protect your output accordingly":
let dump e =
let rec aux prio = function
| Int a -> string_of_int a
| Float a -> string_of_float a
| Add (e1,e2) ->
wrap_if (prio > Prio.add) (aux Prio.add e1 ^ "+" ^ aux Prio.add e2)
| Sub (e1,e2) ->
wrap_if (prio > Prio.add) (aux Prio.add e1 ^ "-" ^ aux Prio.sub e2)
| Mult (e1,e2) ->
wrap_if (prio > Prio.mul) (aux Prio.mul e1 ^ "*" ^ aux Prio.mul e2)
| Div (e1,e2) ->
wrap_if (prio > Prio.mul) (aux Prio.mul e1 ^ "/" ^ aux Prio.div e2)
in aux Prio.add e
;;
It sounds to me like you want to build some set of reduction rules which can be applied to yield the "prettified" or most-reduced form of your expressions, based on order of operations and e.g. commutativity, associativity, etc. For instance (a + a) => a + a, (a * b) + c => a * b + c and so on.
A rather simple and yet rather generic answer (works for other syntaxes than mathematical expressions) : pick precedences (and, if you're picky, associativities) for your constructors, and only add parentheses when a subterm constructor has lower precedence than the current constructor.
More precisely : when you want to print a constructor C(x1,x2,x3..), you look at the head constructor of each xi (if x1 is D(y1,y2..), its head constructor is D), compare the precedence levels of C and D. If the precendence of D is lower, you add parenthesis around the string representation of x2.

Resources