Applying a function n times - functional-programming

I am trying to apply a function to a value n times.
Currently, I have
let rec n_times (f, n, v) =
if n > 0 then
n_times f n-1 (f v)
else
v
For some reason I keep getting an error that says
This expression has type 'a but an expression was expected of type 'a * int * 'b
The type variable 'a occurs inside 'a * int * 'b
I saw a few posts that address the same problem I am working on but none of them gets the same error.

In the first line of your code: you say "I declare a function called n_times that take a triplet (f, n, v) so one argument" then at the call site (third line) you give 3 arguments.
To fix this: write let rec n_times f n v = on line 1 or n_times (f, n-1, (f v)) on line 3.

You have defined the function to take a 3-tuple of values. So when you call it recursively you need to supply a 3-tuple:
n_times (f, n - 1, f v)

There are at least two problems, it would help to know what the purpose is other than recursion.
To get this to run you have to change your third line. n_times is defined with three inputs so it needs to be called with three. Also the function is defined to take a general, integer, and general input and output a general type.
You could remove (f v) and input just v every loop,
# let rec n_times (f, n, v) =
if n > 0 then
n_times (f , n-1 , v)
else
v;;
val n_times : 'a * int * 'b -> 'b = <fun>
# n_times(2,3,4);;
- : int = 4
This will however always return just v at the end.
You could also replace (f v) with a list and preapped it each loop,
# let rec n_times (f, n, v) =
if n > 0 then
n_times (f , n-1 , f::v)
else
v;;
val n_times : 'a * int * 'a list -> 'a list = <fun>
# n_times(2,3,[4]);;
- : int list = [2; 2; 2; 4]
# n_times(2,5,[4]);;
- : int list = [2; 2; 2; 2; 2; 4]
This allows the list to grow with each loop.

There seems to be a misunderstanding in how OCaml functions with multiple arguments are defined. You should replace
let rec n_times (f, n, v) =
with:
let rec n_times f n v =

Related

How do we combine drop n elements from a list and take n elements from a list?

We can create function that take n elements from a list, and drop n elements from a list, as the following:
let rec take n l =
if n = 0 then [] else
match l with
h::t -> h::take(n-1) t
Similarily,
let rec drop n l =
if n = 0 then l else
match l with
h::t -> drop(n-1) t
But how do we combine take and drop function such that it returns a pair with the result of dropping n elements and adding n elements from a list l?
let rec add_drop n l =
if n = 0 then ([],l) else
match l with
h::t -> let (a,b) = add_drop (n-1) t in
(h::a, b)
This is also available in ocaml-containers as take_drop:
val take_drop : int -> 'a t -> 'a t * 'a t
And in Jane Street's Base as split_n
val split_n : 'a t -> int -> 'a t * 'a t
I'd use a tail-recursive approach, with a helper function that builds up the first N elements in an extra argument, originally in reverse order, and then reversing that list before returning it. That way it takes the same stack space no matter how big N is.
let split n lst =
let rec helper n lst head =
if n = 0 then
head, lst
else
match lst with
| car :: cdr -> helper (n - 1) cdr (car :: head)
| [] -> head, [] (* List is shorter than n *) in
let head, tail = helper n lst [] in
List.rev head, tail

Combine a list of functions into a single function using fold

Lets say I have a list of functions
let plus_one (x: int) : int = x + 1 in
let double (x: int) : int = x * 2 in
let square (x: int) : int = x * x in
let fun_list = [square, double, plus_one] ;;
Using fold, I want to take this list of functions and combine them into a single function. Something like,
let combined (x: int) : int = x * (2 * (x + 1))
This is what I have:
let combine_functions (fun_list : ('a -> 'a) list) : ('a -> 'a) =
List.fold_right (fun f acc -> f acc) fun_list (fun x -> x)
;;
I would think this would work, however when I try to run this, it tells me that this expression has type 'a -> 'a when it should have type ('a -> 'a) -> ('a -> 'a)
I've solved this by changing the second line of code from
List.fold_right (fun f acc -> f acc) fun_list (fun x -> x)
to
List.fold_right (fun f acc -> (fun x -> f (acc x))) fun_list (fun x -> x)
I'm a bit unclear on what sort of combination you want, do you mean functional composition? If that's the case, then your combined function would look something like this:
square (double (plus_one x))
or
((x + 1) * 2) * ((x + 1) * 2)
which could be achieved by the function
let combine_functions ls =
List.fold_right (fun f x -> f x) ls;;
However I'm not totally sure if this is really what you're trying to do. As an aside, you don't need to explicitly type all your OCaml code, and I personally find that I'm more productive when I let the type inference do it for me.

OCaml apply anonymous function without argument n-times?

How would I go about applying a function n-times in OCaml if I don't
know the functions argument?
I want the call iter(n, fun x -> 2+x) 0 to evaluate to 2*n since
that would be the same as 2+2+2+2.... Also, if n=0 it should
return the identity function.
My attempt:
let rec iter : int * (int -> int) -> (int -> int)
= fun (n,f) ->
if n = 0 then f
else iter((n-1), f( f () ))
Possible duplicate: OCaml recursive function to apply a function n times but this question has an argument for the anonymous function so the answers does not help me.
You may not “have an argument” right now, but since the result is a function you can always just bring an argument in scope by returning a lambda:
let rec iter : int * (int -> int) -> (int -> int)
= fun (n,f) ->
if n = 0 then f
else fun x -> iter(n-1, f) (f x);;
Try it online!
Note that, as Willem remarks, your base case is probably wrong: for n=0, you want to return the identity function regardless of what function is passed in. Otherwise you get strange behaviour, for instance such a function should generally fulfill iter (n, fun x -> x+1) 0 ≡ n, but with your base case it gives n+1.
I would write the function thus:
let rec iter : int -> ('a -> 'a) -> ('a -> 'a)
= fun n f x -> if n = 0
then x
else iter (n-1) f (f x);;
Try it online!
Here I've not explicitly mentioned the identity function, but because I just return x when n is zero, that's what the identity function does. Alternatively, you can return another lambda which just passes the argument through:
let rec iter : int -> ('a -> 'a) -> 'a -> 'a
= fun n f ->
if n = 0
then fun x -> x (* identity function *)
else fun x -> iter (n-1) f (f x);;
I am not really sure if this is what you want - a small modification of the answer you linked to seems to do the job though:
*Edit: identity function depends on the nature of the function you pass to iter (right?), so I am not really sure how you can get it just from looking at f. That's why I am only returning f for now. And repeat fun x -> x + 2 n times - wouldn't that give you x + 2 * n?
let iter n f =
let chain_func f1 f2 arg = f1 (f2 arg) in
let rec aux n f newf =
if n <= 0 then newf else aux (n - 1) f ( chain_func f newf ) in
aux (n - 1) f f;;
*Edit 2: identity function is fun x -> x so the last line needs to be fixed to: aux n f (fun x -> x)

how to split a list into two lists in which the first has the positive entries and the second has non-positive entries-SML

I am a new to SML and I want to write a function splitup : int list -> int list * int list that given a list of integers creates from two lists of integers, one containing the non-negative entries, the other containing the negative entries.
Here is my code :
fun splitup (xs :int list) =
if null xs
then ([],[])
else if hd xs < 0
then hd xs :: #1 splitup( tl xs)
else hd xs :: #2 splitup( tl xs)
Here's the warning i get:
ERROR : operator and operand don't agree
ERROR : types of if branches do not agree
The function splitup(tl xs) should return int list * int list so i think my recursion should be all right.
What is the problem and how can i fix it ?
The problem is that
hd xs :: #1 splitup( tl xs)
and
hd xs :: #2 splitup( tl xs)
are lists – you can tell from the :: – not pairs of lists as the result should be.
For the non-empty case, you need to first split the rest of the list, then attach the head to the correct part of the result and add it the other part of the result in a pair.
It's also a good idea to get used to pattern matching, as it simplifies code lot.
Something like this:
fun splitup [] = ([], [])
| splitup (x::xs) = let (negatives, non_negatives) = splitup xs
in if x < 0
then (x :: negatives, non_negatives)
else (negatives, x :: non_negatives)
end
There is already List.partition: ('a -> bool) -> 'a list -> 'a list * 'a list, a higher-order library function that does this. In case you want to split up integers into (negative, non-negative):
val splitup = List.partition (fn x => x < 0)

How to do an addition on a list with a condition?

I have a university course about functional programming, where I use SML. As a preparation for the exam, I am working on some of the older exam sets without solutions.
One of the only questions I really have problems with is the following question using foldl:
Consider the program skeleton: fun
addGt k xs = List.foldl (...) ... xs;
Fill in the two missing pieces
(represented by the dots ...), so that
addGt k xs is the sum of those
elements in xs, which are greater than
k. For example, addGt 4 [1, 5, 2, 7,
4, 8] = 5 + 7 + 8 = 20
I am sure this is really easy, but I have a very hard time understanding the foldl and foldr functions.
What I have now is the following (which seems to be very wrong if you ask my compiler!):
fun addGt(k,xs) = List.foldl ( fn x => if x > k then op+ else 0) 0 xs;
I would really appreciate some help with this question, and maybe a very short comment which would cast some light on the foldl and foldr functions!
A solution that I just though of is the following:
fun addGt(k, xs) = List.foldl (fn (x, y) => if x >= 5 then x + y else y) 0 xs;
But let me explain. First of all check the type of the List.foldl function, it's:
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
So List.foldl is a curried function that takes as first parameter another function of type ('a * 'b -> 'b). You used (fn x => if x > k then op+ else 0) which has type int -> int. You should instead provide List.foldl with a function that takes a tuple of type int * int and returns an int, so something like this: (fn (x, y) => do stuff). That's why your code didn't compile, you passed a wrong type of function in foldl.
Now you can think of foldl this way:
foldl f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_n, f(x_(n - 1), ..., f(x2, f(x1, b)) ...)) where f is a function of type ('a * 'b -> 'b), b is something of type 'b and the list [x_1, x_2, ..., x_(n - 1), x_n] is of type 'a list.
And similar for foldr you can think it in this way:
foldr f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_1, f(x_2, ..., f(x_(n - 1), f(x_ n, b))
If you call foldl f s ls on a list, ls = [x1, x2, ..., xn], then you get the result:
f(xn, ... f(x2, f(x1, s)))
That is, it starts by finding
a1 = f(x1, s)
Then
a2 = f(x2, a1)
and so on, until it's through the list.
When it's done, it returns an.
You can think of the a-values as being a sort of accumulator, that is, ai is the result as it would be if the list was only [x1, x2, ..., xi] (or rather, the first i elements of the list).
Your function will usually have the form:
fn (x, a) => ...
What you then need to do is think: Okay, if I have the next element in the list, x(i+1), and the value ai, which is the result for the list [x1, x2, ..., xi], what do I need to do to find the value a(i+1), which is the result for the list [x1, x2, ..., xi, x(i+1)].
s can be thought of as the value given to the empty list.
foldr works the same way, only you start from the back of the list instead of from the front.

Resources