I am new to F# and haven't done functional programming since I was an undergraduate, but I've been trying teach myself. I wrote a naive recursive Extended Euclidean implementation, which works just fine, and am now trying again but with continuations.
I walked through the code by hand twice with a small example and got the correct answer, but when I run it through the interpreter I am not getting the same result, so I'm clearly misunderstanding something I am trying to do.
I ran eea 7 3 by hand, and the (correct) result I computed was (1, 1, -2)
But when I run it in the interpreter I get
eea 7 3;;
val it : int * int * int = (1, 0, 1)
Here's my implementation:
let eea a b =
let rec contEEA a b f =
match b with
| 0 -> f () (a,1,0)
| _ ->
contEEA b (a%b) (fun () t ->
let (d,x',y') = t
(d, y', x'-(y'*(a/b)))
)
contEEA a b (fun () t -> t)
For reference the naive approach, straight from a textbook, is
let rec eea_gcd a b =
match b with
| 0 -> (a, 1, 0)
| _ ->
let d, x', y' = eea_gcd b (a % b)
(d, y', x'-(y'*(a/b)))
Your continuation-based version is always doing exactly one iteration (the last one). When you make the recursive call, your continuation just straight up returns the result instead of "returning" it to the previous call by passing to the previous continuation.
So the call sequence goes like this:
eea 7 3
contEEA 7 3 (fun () t -> t)
b <> 0 ==> second case matches
contEEA 3 1 (fun () t -> ... (d, y', ...))
b <> 0 ==> second case matches
contEEA 1 0 (fun () t -> ... (d, y', ...))
b = 0 ==> first case matches
The continuation is called f () (1, 1, 0)
The continuation calculates result (1, 0, 1 - (0*(3/1)) = (1, 0, 1) and immediately returns it
What you want to do instead is when the first continuation calculates the result of (1, 0, 1) it should pass it to the previous continuation, so that it may carry on the calculations from there, ultimately passing the result to the very first continuation fun () t -> t, which returns it back to the consumer.
To do that, replace this line:
(d, y', x'-(y'*(a/b)))
With this:
f (d, y', x'-(y'*(a/b)))
Also, a few notes on some other aspects.
The first parameter of the continuation (the unit, ()) is not necessary, since it's never actually used (and how can it be?). You can lose it.
After removing the unit parameter, the first continuation becomes fun t -> t, which has a special name id (aka "the identity function")
Rather than destructure the triple with a let, you can do it right in the parameter declaration. Parameters can be patterns!
Applying all of the above, as well as the actual problem fix, here's a better version:
let eea a b =
let rec contEEA a b f =
match b with
| 0 -> f (a,1,0)
| _ ->
contEEA b (a%b) (fun (d,x',y') ->
f (d, y', x'-(y'*(a/b)))
)
contEEA a b id
Related
As the documentation on OCaml is sparse, i would appreciate if some one can explain the difference in different flavors of let usage.
I tried looking into https://dev.realworldocaml.org/toc.html, but there is no easy way to search in the website. Google search landed me to some articles, but did not get the exact explanation.
The basic form of let expressions is:
let p1 = e1
and p2 = e2
...
and pN = eN
in e
where N is at least 1. In this form, let expressions pattern matches the value that results from evaluating the RHS expressions against the LHS patterns, then evaluates the body with the new bindings defined by the LHS patterns in scope. For example,
let x, y = 1, 2 in
x + y
evaluates to 3.
When let has an operator name attached, it is the application of what is called a "let operator" or "binding operator" (to give you easier terms to search up). For example:
let+ x, y = 1, 2 in
x + y
desugars to (let+) (1, 2) (fun (x, y) -> x + y). (Similar to how one surrounds the operator + in parentheses, making it (+), to refer to its identifier, the identifier for the let operator let+, as it appears in a let expression, would be (let+).)
Finally, when a let binding has an operator name attached, all the and bindings must have operator names attached as well.
let* x = 1
and+ y = 2
and* z = 3 in
x + y + z
desugars to (let*) ((and+) 1 ((and*) 2 3)) (fun ((x, y), z) ->).
The following program is invalid and has no meaning because the let binding is being used as an operator, but the and binding is not:
let* x = 1
and y = 2 in
x + y
Binding operators are covered in the "language extensions" section of the OCaml documentation.
let () = e is merely the non-operator form of a pattern match, where () is the pattern that matches the only value of the unit type. The unit type is conventionally the type of expressions that don't evaluate to a meaningful value, but exist for side effects (e.g. print_endline "Hello world!"). Matching against () ensures that the expression has type (), catching partial application errors. The following typechecks:
let f x y =
print_endline x;
print_endline y
let () =
f "Hello" "World"
The following does not:
let f x y =
print_endline x;
print_endline y
let () =
f "Hello" (* Missing second argument, so expression has type string -> unit, not unit *)
Note that the binding operators are useful for conveniently using "monads" and "applicatives," so you may hear these words when learning about binding operators. However, binding operators are not inherently related to these concepts. All they do is desugar to the expressions that I describe above, and any other significance (such as relation to monads) results from how the operator was defined.
Consider the following code from the OCaml page on let operators.
let ( let* ) o f =
match o with
| None -> None
| Some x -> f x
let return x = Some x
If we create a very simply map:
module M = Map.Make (Int)
let m = M.(empty |> add 1 4 |> add 2 3 |> add 3 7)
If we wanted to write a function that takes a map and two keys and adds the values at those keys, returning int option, we might write:
let add_values m k1 k2 =
match M.find_opt k1 m with
| None -> None
| Some v1 ->
match M.find_opt k2 m with
| None -> None
| Some v2 ->
Some (v1 + v2)
Now, of course there are multiple ways of defining this. We could:
let add_values m k1 k2 =
match (M.find_opt k1 m, M.find_opt k2 m) with
| (None, _) | (_, None) -> None
| (Some v1, Some v2) -> Some (v1 + v2)
Or take advantage of exceptions:
let add_values m k1 k2 =
try
Some (M.find k1 m + M.find k2 m)
with
| Not_found -> None
Let operators let us write:
let add_values m k1 k2 =
let* v1 = M.find_opt k1 m in
let* v2 = M.find_opt k2 m in
return (v1 + v2)
I am doing some exercises on F#, i have this function that calculate the alternate sum:
let rec altsum = function
| [] -> 0
| [x] -> x
| x0::x1::xs -> x0 - x1 + altsum xs;;
val altsum : int list -> int
The exercise consist in declare the same function with only two clauses...but how to do this?
The answer of mydogisbox is correct and work!
But after some attempts I found a smallest and readable solution of the problem.
let rec altsum2 = function
| [] -> 0
| x0::xs -> x0 - altsum2 xs
Example
altsum2 [1;2;3] essentially do this:
1 - (2 - (3 - 0)
it's is a bit tricky but work!
OFF TOPIC:
Another elegant way to solve the problem, using F# List library is:
let altsum3 list = List.foldBack (fun x acc -> x - acc) list 0;;
After the comment of phoog I started trying to solve the problem with a tail recursive function:
let tail_altsum4 list =
let pl l = List.length l % 2 = 0
let rec rt = function
| ([],acc) -> if pl list then -acc else acc
| (x0::xs,acc) -> rt (xs, x0 - acc)
rt (list,0)
This is also a bit tricky...substraction is not commutative and it's impossible think to revers with List.rev a long list...but I found a workaround! :)
To reduce the number of cases, you need to move your algorithm back closer to the original problem. The problem says to negate alternating values, so that's what your solution should do.
let altsum lst =
let rec altsumRec lst negateNext =
match lst with
| [] -> 0
| head::tail -> (if negateNext then -head else head) + altsumRec tail (not negateNext)
altsumRec lst false
Why is the following code giving me that error?
Note that the is_sorted function returns either true or false
and make_move function returns a list of lists. e.g [[0,1,3,2],[1,0,2,3]]
let rec solve_helper b pos n r fn =
if n = 0 then b :: r :: fn (*fn is the final array with all paths*)
else match pos with
[] -> fn
|(h::t) -> if is_sorted h = true then h
else h :: r (* ERROR HERE: r is the temp array that contains 1 path*)
solve_helper b (make_moves h) (n-1) r
solve_helper b t (n-1) r (*tail recursion*)
;;
let solve_board b n = solver_helper b (make_moves b) n [] []
;;
new code:
let rec solve_helper b pos n r fn =
if n = 0 then r :: fn (*fn is the final array with all paths*)
else match pos with
[] -> fn
|(h::t) -> if is_sorted h = true then
let j = h :: r in
r :: fn
else
let u = h :: r in
let k = solve_helper b (make_moves h) (n - 1) r fn in
solve_helper b t (n - 1) r fn(*tail recursion*)
;;
let solve_board b n = solve_helper b (make_moves b) n [] []
;;
These lines of your code:
else h :: r (* ERROR HERE: r is the temp array that contains 1 path*)
solve_helper b (make_moves h) (n-1) r
solve_helper b t (n-1) r (*tail recursion*)
do not make sense as far as I can tell. They represent a call to a function named r with 10 arguments (two of which are the function r itself).
Possibly you need to edit your code to show exactly what the compiler is seeing.
If your code actually looks like this, you need to rethink this part. It reads like imperative code (a series of things to do) rather than functional code (an expression consisting of functions applied to arguments).
Is it possible to have nested if without else statements. I wrote the following useless program to demonstrate nested ifs. How do I fix this so it's correct in terms of syntax. lines 5 and 6 gives errors.
let rec move_helper b sz r = match b with
[] -> r
|(h :: t) ->
if h = 0 then
if h - 1 = sz then h - 1 ::r
if h + 1 = sz then h + 1 ::r
else move_helper t sz r
;;
let move_pos b =
move_helper b 3 r
;;
let g = move_pos [0;8;7;6;5;4;3;2;1]
You can't have if without else unless the result of the expression is of type unit. This isn't the case for your code, so it's not possible.
Here's an example where the result is unit:
let f x =
if x land 1 <> 0 then print_string "1";
if x land 2 <> 0 then print_string "2";
if x land 4 <> 0 then print_string "4"
You must understand that if ... then is an expression like any other. If no else is present, it must be understood as if ... then ... else () and thus has type unit. To emphasize the fact that it is an expression, suppose you have two functions f and g of type, say, int → int. You can write
(if test then f else g) 1
You must also understand that x :: r does not change r at all, it constructs a new list putting x in front of r (the tail of this list is shared with the list r). In your case, the logic is not clear: what is the result when h=0 but the two if fail?
let rec move_helper b sz r = match b with
| [] -> r
| h :: t ->
if h = 0 then
if h - 1 = sz then (h - 1) :: r
else if h + 1 = sz then (h + 1) :: r
else (* What do you want to return here? *)
else move_helper t sz r
When you have a if, always put an else. Because when you don't put an else, Java will not know if the case is true or false.
Can everyone explain to me this piece of code ?
let safe_division n = function
| 0 -> failwith "divide by 0"
| m -> n / m
When I excute safeDiv 3 0 , what is the m and n in this case ?
In general case, when does the function match the first and second pattern ?
It is easy to see what this means once you realise that
let f x y z = e
is just a short-hand for
let f = function x -> function y -> function z -> e
That is, a function of n arguments actually is n nested functions of 1 argument. That representation is called "currying". It is what allows you to apply a function partially, e.g.
let g = f 3
returns a function of 2 arguments.
Of course, the short-hand above can be mixed freely with the explicit form on the right, and that's what your example does. You can desugar it into:
let safe_division = function n -> function
| 0 -> failwith "divide by 0"
| m -> n / m
When you execute safe_division 3 0, first, 3 is bound to the name n and the right-hand side of the declaration is then evaluated.
This is a function, so the next argument, 0, is matched against the different cases, in order. Here, it matches the first case, so the right-hand side is evaluated and an exception is thrown. In this case, the name m is never bound to anything.
If the second argument was, for example, 1, then it would have matched the second case (this case matches every possible value anyway, it's a default case), binding the name m to the value 1 and then returning the result of n / m.
let safe_division n
define a function which type is int -> ...
function
| 0 -> failwith "divide by 0"
| m -> n / m
define a function which type is int -> int
So the resulting type of the whole is int -> int -> int where n is the first argument, and m the second. The last int is the result.
let safe_division n = function
| 0 -> failwith "divide by 0"
| m -> n / m
is just equivalent to:
let safe_division n = fun x -> match x with
| 0 -> failwith "divide by 0"
| m -> n / m
Note fun and function are slightly different. See: Function definition.