Ocaml use of a recursive function - recursion

I have to write a recursive function that calculates the sum of all the positive integers smaller than n.
My function works at top level but I cannot manage to use it in a script:
let rec sum x =
if x = 0 then 0 else x + sum (x - 1)
let () =
Printf.printf "%d\n" sum 4
I get the following error at compilation:
Error: This expression has type
('a -> 'b, out_channel, unit, unit, unit, 'a -> 'b)
CamlinternalFormatBasics.fmt
but an expression was expected of type
('a -> 'b, out_channel, unit, unit, unit, unit)
CamlinternalFormatBasics.fmt
Type 'a -> 'b is not compatible with type unit
for the last line.

You are missing some parentheses. You want this:
let () =
Printf.printf "%d\n" (sum 4)
This would not have worked in toplevel either.
Without the parentheses, you are asking to pass sum (your function itself) as a parameter to printf.

Related

Stack Overflow when calling a function that generates a lazy list?

I can define an infinite data structure - aka lazy list - like this.
let 'a lazylist = Succ of 'a * (unit -> 'a lazylist);;
(Why can't I replace unit -> 'a lazylist with () -> 'a lazylist?)
The way I understand lazy data structures the above definition says that a lazy list consists of a tupel of a generic element 'a and a function unit->'a lazylist that will compute the next element in the list when called with () which is of type unit.
So e.g. I could generate a list that has every even number:
let rec even_list l =
match l with
Succ (a, l') ->
if (a mod 2 = 0) then
Succ (a, fun() -> even_list (l' ())
else
even_list (l' ());;
The way I understand it: When fun() -> even_list (l'())) is called with the unit argument () it will call even_list with the successor of l' by giving it unit as an argument: l'()
But is it possible for the else even_list (l'());; part to lead to a Stack Overflow if we give even_list a lazylist as an argument that only consists of uneven elements e.g.? Whereas in the then part of the if-statement we only generate the next element of the list when called with () - in the else part we would search indefinitely.
First, you can use the built-in Seq.t type rather than define your own lazy list type.
Second, your function even_list is tail-recursive and cannot result in a stack overflow.
Third, if you are using the take function proposed in Call lazy-list function in OCaml, it is this function which is not tail-recursive and consumes stack.
You can write a tail-recursive version of this function
let rec take l n (Succ(x,f)) =
if n = 0 then List.rev l
else take (x::l) (n-1) (f ())
let take n l = take [] n l
or define a fold function
let rec fold_until n f acc (Succ(x,l)) =
if n = 0 then acc
else fold_until (n-1) f (f acc x) (l())
and use that function to define a printer that does not build an intermediary list.
(This is why it is generally advised to write-down a fully self-contained example, otherwise the issue is too often hidden in the implicit context of the question.)

How to write a function that appends a variable number of elements to a lazy list with each iteration?

The motivating problem is: Code a lazy list whose elements are all possible combinations of 0 and 1 i.e. [0], [1], [0;0], [0;1], etc..
Working in OCaml, I've written auxiliary functions for generating the list of permutations of length n+1 given n and for converting a list into a lazy list. The problem comes from the final function in the below block of code:
type 'a seq =
| Nil
| Cons of 'a * (unit -> 'a seq)
let rec adder = function
| [] -> []
| [[]] -> [[0];[1]]
| xs::ys -> (0::xs)::(1::xs)::(adder ys)
let rec listtoseq = function
| [] -> Nil
| xs::ys -> Cons(xs, fun () -> listtoseq ys)
let rec appendq xq yq =
match xq with
| Nil -> yq
| Cons (x, xf) -> Cons (x, fun() -> appendq (xf ()) yq)
let genlist xs = appendq (listtoseq xs) (genlist (adder xs))
Calling genlist [[0];[1]] results in a stack overflow. The issue seems to be that since genlist is an infinite loop I want to delay evaluation, yet evaluation is needed for appendq to work.
If this were a problem where one element is added to the lazy list at a time I could solve it, but I think the difficulty is that each set of length n permutations must be added at a time, and thus I don't know any other solution besides using an append function.
One way to look at your problem is that appendq isn't lazy enough. You can make things work if you define a function appendqf with this type:
'a seq -> (unit -> 'a seq) -> 'a seq
In other words, the second parameter isn't a sequence. It's a function that returns a sequence.
(Note that this type, unit -> 'a seq, is what actually appears inside a Cons.)
I tried this and it works for me.

How to Accumulate Observables

I should define a function, which will return IObservable<'u>
accumulate : ('t -> 'a -> 't * 'u option) -> 't -> IObservable<'a> -> IObservable<'u>
So that my function f t obs' accumulates observable events of obs into an accumulator of type 't and emits an observable event u when 'snd (f acc a)' evaluates to 'Some u' for an observed event 'a'.
So far I have implemented the function below:
let accumulate (f:'t -> 'a -> 't * 'u option) t obs =
Observable.scan (fun _ x -> snd (f t x)) None obs
I really don't understand how this observable scan thing works, my function returns IObservable<'u option> in this case. How can I fix that? Am I on the right track?
The function fun _ x -> snd (f t x) is incomplete. The clue is that the first parameter _ is ignored and the first part of the resulting tuple is thrown away by the call to snd.
There is no accumulation because f t x always calls with the same value t that was passed originally to accumulate. That original t is supposed to be the initial value and should be passed to scan as part of its second parameter.
The first part of the tuple produced by f:'t -> 'a -> 't * 'u optionis the accumulated value. So that is that part that needs to be returned to scan so that it gets passed to f again and accumulated over and over.
In your problem the requirement is to accumulate and also pass an event when the second part of the tuple is Some 'u. So the question is how to do both: accumulate 't and filter 'u?
The answer is by combining the accumulated value with the Some 'u which is what f does. So you need to keep the tuple as the scan state and then afterwards keep only the second part using choose and snd.
This is what you are looking for:
let accumulate (f:'t -> 'a -> 't * 'u option) t obs =
obs
|> Observable.scan (fun (acc, _) x -> f acc x) (t, None)
|> Observable.choose snd
Understanding scan
scan is a function that carries a changing state by passing it to a function together with a series of values. In particular it can be used to accumulate values, for instance an int running total:
let keepTotal obs =
obs
|> Observable.scan (fun total v -> total + v) 0
This is equivalent to doing this in imperative code with a mutable total :
let mutable total = 0
let keepTotal2 obs =
obs
|> Observable.map (fun v ->
total <- total + v
total
)
notice how the 2 versions have the same elements:
initial value: 0
accumulator function: total + v
Of course the second version, even though it uses map, is bad functional code because it uses an external mutable variable which is a big NO NO.
Your original problem could have been solved the same way:
let accumulate2 (f:'t -> 'a -> 't * 'u option) t obs =
let mutable acc = t
obs
|> Observable.choose (fun x ->
let acc2, uOp = f acc x
acc <- acc2
uOp
)
Even though this one uses a mutable variable which is ugly in functional programming (and unnecessary) it is functionally ok, because the variable acc is internal and no code outside accumulate2 can see it. Still ugly though.
You can chain an Observable.choose after your Observable.scan to get the correct type signature
let accumulate (f:'t -> 'a -> 't * 'u option) t obs =
obs
|> Observable.scan (fun _ x -> snd (f t x)) None
|> Observable.choose id

Ocaml error Printf.printf

let main() =
let base = read_int () in
let num = read_int () in
if num = reverse num && (is_base base num) = true then Printf.printf "YES"
else if is_base base num = false then Printf.printf "ERROR"
else Printf.printf"NO"
This expression has type
('a -> 'b -> 'c, out_channel, unit, unit, unit, 'a -> 'b -> 'c)
CamlinternalFormatBasics.fmt
but an expression was expected of type
('a -> 'b -> 'c, out_channel, unit, unit, unit, unit)
CamlinternalFormatBasics.fmt
Type 'a -> 'b -> 'c is not compatible with type unit
I've read the documentation, but it's still not clear how printf works in Ocaml.
It works in toplevel. Maybe some library missing?
With a high probability the next line of your code is
main ()
or a similar toplevel expression, and this is the true source of your error. Toplevel expression needs to be introduced by ;;:
;; main ()
Another idiom is to rather write
let () = main ()
to avoid introducing toplevel expressions at all
Now, why did you get such a complicated type error? The answer is quite interestings and stems from the left-to-right bias of the typechecker and the flexibility of printf. Everything starts when we write:
Printf.printf "ERROR" main ()
Here, the type of Printf.printf is ('a, out_channel, unit) format -> 'a which means:
'a: printf takes a format string plus as many argument as required by the format
out_channel: it writes on a out_channel
unit : ultimately, it returns unit.
But then, when typing the function application,
Printf.printf "Error" main (), the typechecker sees that Printf.printf is applied to three argument, it thus deduces that the type 'a can be expanded to 'b -> 'c -> 'd. But then, the typechecker looks at the type of the format argument "ERROR": ('e, 'f, 'e) format, it infers thus that the return type of the format should be 'b -> 'c -> 'd. But this is a contradiction with the fact that Printf.printf required unit as a return type, leading to your type error (after a bit of simplification):
('a -> 'b -> 'c, out_channel,'a -> 'b -> 'c) format
but an expression was expected of type
('a -> 'b -> 'c, out_channel, unit) format
Type 'a -> 'b -> 'c is not compatible with type unit

OCaml - Accumulator Using Fold Left

Learning OCaml from here.
I want to verify if I have understood how this snippet of OCaml code works
List.fold_left (fun acc x -> acc + x) 0 [ 1; 2; 3; 4 ]
I have an intuition that this is an equivalent to the reduce function in Python. Specifically, I think it is equivalent to
reduce(lambda x, y: x + y, [1, 2, 3])
The anonymous function is taking two parameters - acc and x and returns a single value acc + x. I understand that initially, the first argument acc will be 0 but how does it know that the second argument has to be the first element of the list?
What I think is happening is that fold_left provides the two arguments to the anonymous function and then recursively calls itself with new arguments until the list becomes empty.
To confirm this I saw this.
When I define a function like let inc x = x + 1 I get something like val inc : int -> int = <fun> but in this case the signature is : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
What is 'a and how should I interpret this function signature so that List.fold_right f [a1; ...; an] b becomes f a1 (f a2 (... (f an b) ...))?
You are asking many questions.
I'm pretty sure that Python reduce is a fold, so your intuition is probably right.
You ask "how does it know that the second argument has to be the first element of the list?" Unfortunately, I don't think this is a well formed question. There's no "it" that knows anything. Most likely the answer is given by the definition of fold_left. It knows what to do because somebody wrote the code that way :-)
Here is the definition of fold_left from the standard library:
let rec fold_left f accu l =
match l with
[] -> accu
| a::l -> fold_left f (f accu a) l
In some sense, this should answer all your questions.
The type 'a in the type of fold_left is the type of the accumulator. The point is that you can use any type you want for the accumulator. This is why the fold is so powerful. As long as it matches the values accepted and returned by the folded function, it can be anything you want.
If I remember correctly, reduce is a simpler version of fold, which takes the first element of the list as starting element. I'd define it this way:
let reduce f = function
| x::xs -> fold_left f x xs
| [] -> failwith "can't call reduce on empty lists!"
If you enter it in OCaml, it will display its type:
val reduce : ('a -> 'a -> 'a) -> 'a list -> 'a
You can contrast it with fold_left's type:
('b -> 'a -> 'b) -> 'b -> 'a list -> 'b
The type variables 'a and 'b here mean that they can stand for any type. In your example, both 'a and 'b become int. If we insert the types, fold_left has the signature:
(int -> int -> int) -> int -> int list -> int
That's what we expected: + is a function which takes two ints and returns a new one, 0 is an int and the [1;2;3;4;] is a list of ints. The case that fold_left has two type variables and reduce only has one already gives a hint that it is more general. To see why we can look at the definition of reduce. Since the starting element of the fold is an element of the list, the types 'a' and 'b must be the same. That's fine for summing up elements, but say, we'd like to construct an abstract syntax tree for our summation. We define a type for this:
type exp = Plus of exp * exp | Number of int
Then we can call:
fold_left (fun x y -> Plus (x, (Number y))) (Number 0) [1; 2; 3; 4]
Which results in the expression:
Plus (Plus (Plus (Plus (Number 0, Number 1), Number 2), Number 3), Number 4)
A benefit of this tree is that you can nicely see what is applied first (0 and 1) - in case of addition this is not a problem, since it is associative (this means a+(b+c) = (a+b)+c) which is not the case for subtraction (compare e.g. 5-(3-2) and (5-3)-2).
If you want to do something similar with reduce, you will notice that OCaml complains about type errors:
reduce (fun x y -> Plus (x, (Number y))) [1; 2; 3; 4] ;;
Error: This expression has type exp but an expression was expected of type
int
In this case, we can wrap each integer as an expression in our input list, then the types agree. Since we already have Numbers, we don't need to add the Number constructor to y:
let wrapped = map (fun x -> Number x) [1; 2; 3; 4] in
reduce (fun x y -> Plus (x, y)) wrapped
Again, we have the same result, but we needed an additional function call to map. In the case of fold_left, this is not necessary.
P.S.: You might have noticed that OCaml gives the type of fold_left as ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a. I guess you will quickly realize that the name of the type variables doesn't play a role. To make it easier to compare, I switched the names such that the function is always applied to a list of 'a.
A little late, but the comparison between OCaml's folds and Python's reduce may be easier if you incorporate reduce's initializer argument.
Summing a list of ints in OCaml using a fold:
let sum = List.fold_left (+) 0 [1; 2; 3]
And using reduce in Python.
from functools import reduce
sum = reduce(int.__add__, [1, 2, 3], 0)
Here you can see the order of arguments is a bit different, but they're all there.
Python feels it's less likely you'll need the initializer, so leaves it at the end as an optional argument as a convenience. OCaml features the list as the last argument also as a convenience, as partial application makes it easy to write something like a sum function.
let sum = List.fold_left (+) 0
Rather than:
let sum lst = List.fold_left (+) 0 lst

Resources