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).
Related
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.
Code:
let isPrime x =
let checkZero d = match (x mod d, x mod d + 2, intRoot x < d) with
| (0,_,_) -> false
| (_,0,_) -> false
| (_,_,true) -> true
| _ -> checkZero (d + 6) in
match x with
| 0 -> false
| 1 -> true
| 2 -> true
| 3 -> true
| _ -> match (x mod 2, x mod 3) with
| (0,_) -> false
| (_,0) -> false
| _ -> checkZero 5
Error:
line 9, characters 24-33:
Error: Unbound value checkZero
Which refers to the recursive call checkZero (d+6)
I've tried placing the checkZero function as a let ... in in the final checkZero 5 call and added/removed the x parameter in the checkZero function in case there was an error with the definition.
(Running OCaml downloaded in the past week on OSX through homebrew)
If you want a function to be able to call itself you need to declare it as recursive:
let rec checkZero d ...
The task is to get scalar value from 2 lists recursively. I wrote the code that I think should work, but I am having some type related problem
let rec scalar2 (a, b) = function
| ([], []) -> 0
| ([x : int], [y : int]) -> x * y
| (h1::t1, h2::t2) ->
let sc : int = scalar2 (t1,t2)
sc + (h1 * h2)
The error is that scalar2 (t1,t2) reqested to be int, but it is int list * int list -> int
How this problem could be solved?
When defining a function using the function keyword, you don't need to name your parameters (a and b here). Note that your function body doesn't refer to a or b at all. You want scalar2 to be a function, and the function expression on the right hand side results in a function, so just assign this function to scalar2 directly.
let rec scalar2 = function
| ([], []) -> 0
| ([x : int], [y : int]) -> x * y
| (h1::t1, h2::t2) ->
let sc : int = scalar2 (t1,t2)
sc + (h1 * h2)
Your mistake is likely caused by a confusion with the usual way of defining a function, which doesn't use the function keyword:
let rec scalar2 (a,b) =
match (a,b) with
| ([], []) -> 0
| ([x : int], [y : int]) -> x * y
| (h1::t1, h2::t2) ->
let sc : int = scalar2 (t1,t2)
sc + (h1 * h2)
This way you need a match expression which does use the parameters a and b.
Note that both of these definitions are incomplete, since you haven't said what should happen when only one of the lists is non-empty.
To explain the type error in the original code, consider how F# evaluates let sc : int = scalar2 (t1,t2). Your original definition says that scalar2 (a,b) = function ..., and the left-hand side of this equality has the same form as the expression scalar2 (t1,t2).
So the scalar2 (t1,t2) gets replaced with the function ... expression, after substituting t1 for a and t2 for b. This leaves let sc : int = function ... which of course doesn't type-check.
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
val compare : bool array array -> 'a list -> 'a list -> int
compare m generates the lexicographical order on list. I don't know how to fill ???
let rec compare m c c' =
match c with
| [] -> (match c' with
| [] -> 0
| _ :: _ -> -1)
| hd1 :: tl1 -> (match c' with
| [] -> 1
| hd2 :: tl2 -> ???
This is a function that I was trying to do by in a list of ints. but this function was not satisfy, it still missing to check in the rest of a list.
let cmp_classes m c c' =
match c, c' with
| i :: _, j :: _ ->
begin
match m.(i).(j), m.(j).(i) with
(* same class: there is a path between i and j, and between j and i *)
| true, true -> 0
(* there is a path between i and j *)
| true, false -> 1
(* there is a path between j and i *)
| false, true -> -1
(* i and j are not compareable *)
| false, false -> 0
end
| _ -> assert false
Could you please help me? Because when I tried with this function in int
let cmp_classes m i j =
match m.(i).(j), m.(j).(i) with
(* same class: there is a path between i and j, and between j and i *)
| true, true -> 0
(* there is a path between i and j *)
| true, false -> 1
(* there is a path between j and i *)
| false, true -> -1
(* i and j are not compareable *)
| false, false -> 0
it still not return the right order in data I test.
I have been doing this function many times, it is really stuck when I have to try again and again but not find out what is wrong. Please I need your help. Thank you
(* i and j are not compareable *)
| false, false -> 0
This is completely wrong if you are trying to make a topologic sort of your elements. You are saying that incomparable elements are equals which is complete nonsense and WILL confuse the sort algorithm.
If you want to have a real topological order you should follow these steps:
build an input list as the list containing only one representant per class; the output list is empty
until the input list is empty:
pick a random root (with no input edge) in the input list and remove it from the list
append (in any order) all elements the root representants in the output list
return the output list
Depending on the data-structures you are using, this algorithm can be more or less efficient, but your question is not enough precise for me to tell you more.