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 ...
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.
The problem is as follow: Given an oriented weighted graph, a start node, an end node and a number k, verify if exist a path from the start node to the end node with at least length k.
This is the code i wrote and it's correct but only in specific graph. For example g1 with weights1 is as follows:
let weights1 = [(2,1,1);(2,1,3);(2,1,4);(1,1,5);(5,1,2);(5,1,6);(3,1,6);(6,1,7);(4,1,3)];;
let f1 = function
1 -> [5]
| 2 -> [1;3;4]
| 3 -> [6]
| 4 -> [3]
| 5 -> [2;6]
| 6 -> [7]
| _ -> [];;
type 'a graph = Graph of ('a -> 'a list);;
let g1 = Graph f1;;
let weights2 = [(1,3,2);(1,9,5);(2,2,3);(5,4,6);(3,1,6);(3,7,4);(6,2,7);(4,4,6);(6,1,2)];;
let f2 = function
1 -> [2;5]
| 2 -> [3]
| 3 -> [4;6]
| 4 -> [6]
| 5 -> [6]
| 6 -> [2;7]
| _ -> [];;
let g2 = Graph f2;;
exception NotFound;;
exception Errore;;
(* Function that return the weight of an edge given 2 nodes*)
let rec get_k x y = function
[] -> 0
|(a,b,c)::rest -> if((a=x && c=y))then b else get_k x y rest;;
(* Function that calculate the total cost of a given path*)
let cost_of_path path weight =
let rec sum cost = function
[]->raise Errore
|x::y::rest -> sum (cost + get_k x y weight) (y::rest)
|_::[]->cost
in sum 0 path;;
(*this function print the list of the path*)
let rec printList = function [] -> print_newline()
| x::rest -> print_int(x); print_string("; "); printList rest;;
(* Simple bfs function, return only 1 path that connect the start node to the final node*)
let bfs start last_node (Graph succ) =
let extends path = printList path;
List.map (function x -> x::path) (List.filter (function x -> not (List.mem x path)) (succ (List.hd path)))
in let rec aux last_node = function
[] -> raise Not_found
| path::rest ->
if (last_node = List.hd path) then List.rev path
else aux last_node (rest # (extends path))
in aux last_node [[start]];;
let loghest_path start final_node k weight (Graph succ)=
let extends path = printList path;
List.map (function x -> x::path)(succ (List.hd path))
in let rec aux final_node = function
[] -> raise NotFound
| path::rest ->
(*if the cost of this path is >= k and the last node is the final node, return that path.*)
if ((cost_of_path (List.rev path) weight >= k) && (List.hd path == final_node)) then List.rev path
(*HERE IS THE ERROR: if the total weight of the singole path is >= k but the last node is not the final node,
find a path that connect the last node of this path to the final node using bfs. It can happen that the path exists
but it return "Not_Found".*)
else if((cost_of_path (List.rev path) weight) >= k)
then (List.rev (List.tl path)) # bfs (List.hd path) (final_node) (Graph succ)
(* If the weight is not yet k than extend the path and try another one in list 'rest' *)
else aux final_node (rest # (extends path))
in aux final_node [[start]];;
(*Function that calls the other function 'loghest_path' and print the result *)
let find_path start final_node k weigths (Graph succ)=
let result = (loghest_path start final_node k weigths (Graph succ)) in
print_string("Final Path:"); printList result ;
print_string("The weight is:"); print_int (cost_of_path result weigths); print_newline();;
And an execution of my code using weights1 and g1 is:
Now, if i execute my code in another graph, for example:
let weights3 =[(1,1,2);(1,1,3);(1,1,4);(2,1,5);(2,1,6);(3,1,7);(3,1,8);(4,1,9);(4,1,10);(10,1,1)];;
let f3 = function
1 -> [2;3;4]
| 2 -> [5;6]
| 3 -> [7;8]
| 4 -> [9;10]
| 10 -> [1]
| _ -> [];;
let g3 = Graph f3;;
With the following execution my code fails:
This because the last path before finding a path that is at least k starts with node 2, and there isn't a path that can connect 2 with 10, but a path between 1 and 10 of weights 10 exists and it's not been chosen. Can someone explain to me how can i change my code to make sure that the problem is solved in every type of graph?
As you stated yourself, the block
else if((cost_of_path (List.rev path) weight) >= k)
then (List.rev (List.tl path)) # bfs (List.hd path) (final_node) (Graph succ)
can fail because nothing ensures the existence of a path from the the last element of the current path to the final node.
The easiest fix is to simply delete this block and ... that's it.
There are no imperious needs to switch algorithms when one partial path is greater than the length threshold (and this is not the right algorithm to try to optimize).
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
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).
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.