As I am going through the website:
http://www.cs.princeton.edu/courses/archive/fall14/cos326/sec/03/precept03_sol.ml
I have got a question according to the Ocaml structure. To be more specific, I have questions according to the code:
let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
match xs with
| [] -> u
| hd::tl -> f hd (reduce f u tl);;
What does the f hd do at the very last line? (I understand that reduce f u tl is calling the function itself again.)
My second question is how to use a function to implement another function in Ocaml. For the code:
let times_x (x: int) (lst: int list) : int list =
map (fun y -> y*x) lst
What does fun y -> y*x do? what does lst do at the end of the code?
Thank you for the help!
The code that has been provided is a reduce function that takes three parameters - a function that maps inputs of type 'a and 'b to an output of type 'b, a value of type 'b, and as list of elements of type 'a.
For example, the length example from the lecture:
let length (lst: int list) : int =
reduce (fun _ len -> len + 1) 0 lst
The first parameter to reduce is a function that, when given two parameters, discards the first one and returns the second parameter incremented by one. The second is a value (0) to be used as an accumulator. The third is a list to find the length of.
The behavior of this recursive reduce function is to return the second parameter (an accumulator as used in the length example) once the provided list is empty, and otherwise run the provided function using the head of the list and the recursed value.
Once again going to the length example, say we give it a list with a single element [1].
Our call to length becomes reduce (fun _ len -> len + 1) 0 [1]
Recall reduce:
let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
match xs with
| [] -> u
| hd::tl -> f hd (reduce f u tl);;
First, we match [1] against [], which fails. Since it is a non-empty list, we run f hd (reduce f u tl)
Recall that f is the parameter that length provided: fun _ len -> len + 1
Therefore, we effectively run the following:
(fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 [])
In this case, the length function discards the first parameter since the values in the list are not necessary to know the length of the list.
The recursive portion will match against [] and return the value of u at the time, which is 0.
Therefore, one level up, (fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 []) becomes (fun _ len -> len + 1) 1 0 and returns 0 + 1, simplifying to our expected value 1, which represents the length of the list.
Now, to your second question, in regards to times_x. This performs a mapping. For example, we can map [1;2;3;4;5] to [3;6;9;12;15] with a mapping fun x -> x * 3.
Here times_x is defined as follows:
let times_x (x: int) (lst: int list) : int list =
map (fun y -> y*x) lst
times_x takes an integer and a list. Using the above example, we could call it with times_x 3 [1;2;3;4;5] to get [3;6;9;12;15].
Beyond this I recommend looking into how map and reduce functions work in general.
I hope this answer was adequate at addressing your question.
Related
I'm trying to rewrite the List.length function without using recursion. Here's my code:
(* given *)
type 'a list =
| []
| (::) of 'a * 'a list
let nil : 'a list = []
let cons (hd : 'a) (tl : 'a list): 'a list = hd :: tl
let length (ls : 'a list): int =
let i = fold_left(fun x y -> Fun.const 1 :: y) [] ls in
fold_left(fun x y -> x + y) 0 i
OCaml gave me an error on the last line fold_left(fun x y -> x + y) 0 i and saying my i here has type ('a -> int) list but an expression was expected of type int list, is there any way I can fix this? Thank you!
It's not entirely clear to me what you are trying to achieve with Fun.const, but you can actually achieve length with a single fold_left:
let length l =
fold_left (fun acc _ -> acc+1) 0 l
There are a few issues with your attempt.
As Fun.const creates in this case a function which always returns 1, and your expression parses as: (Fun.const 1) :: y your first use of List.fold_left is generating a list of functions which all return one. But there are not the value 1.
Thus when you use fold_left (fun x y -> x + y) 0 i you are trying to add a function to an int. Clearly this doesn't work. You need to apply some argument to that function.
let length (ls : 'a list): int =
let i = List.fold_left(fun x y -> Fun.const 1 :: y) [] ls in
List.fold_left(fun x y -> x + y ()) 0 i
This compiles. But... the type doesn't look quite right.
val length : (unit -> int) list list -> int = <fun>
This results from having the argument order to the function List.fold_left takes wrong. The first argument is the initial value. The second is the first element from the list.
If we change that:
let length (ls : 'a list): int =
let i = List.fold_left(fun y _ -> Fun.const 1 :: y) [] ls in
List.fold_left(fun x y -> x + y ()) 0 i
The type of this function is:
val length : 'a list -> int = <fun>
But as Blackbeans has noted, there is a much simpler way to write this using a single call to List.fold_left.
I’m trying to create a function that takes an int list as an argument and returns the sum of the product between an int and its position in the list. To put in an example this : multSum [5; 11; 15] should return (5 * 1 + 11 * 2 + 15 * 3) = 72.
It should be written recursively and I’m trying while avoiding List.map or List.filter or any other prefabricated functions.
By dividing and reigning the query above, I have so far started by trying the following :
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t ;;
val tir : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
then I moved to this :
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto";;
val carto : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
with the final idea to be able to do that :
let prod arg1 arg2 =
tir (+) 1 (carto ( * ) arg1 arg2);;
val prod : int list -> int list -> int = <fun>
But I am stuck now and I’m not sure of my orientation from here forward. I thought of trying to search for the index in a "l" and replace each index int in the acc, in order to make it work but I'm afraid I'm rather complicating things... Any help please ?
Edit 1 :
let rec multSum l =
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t)in
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t in
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto" in
let prod arg1 arg2 =
tir (+) 0 (carto ( * ) arg1 arg2) in
prod l (indices 1 l);;
val multSum : int list -> int = <fun>
Building on your replies, surely these are 'fold' and 'map' rewritten. At least, I'm sure now that I was on the right track. I have come to put together the whole code as signaled above in Edit 1.
It seems to be working well... I know that I want a recursive function and here it is. But, do you think it could be done even shorter recursively of course?
#coredump is quite right about this looking like an ideal scenario for a fold, but the extra functions aren't really that necessary. We can just use a tuple to pass the index and sum information around, then when we're done, discard the index information from the tuple.
let sum_list_prod lst =
let (_, result) = List.fold_left
(fun (i, sum) x -> (i + 1, sum + i * x))
(1, 0)
lst
in
result
Edit: A simple implementation of a left fold to demonstrate the recursion going on here.
let rec foldl f init lst =
match lst with
| [] -> init
| first :: rest -> foldl f (f init first) rest
So working through a simple example with sum_list_prod:
sum_list_prod [2; 3; 4]
Calls the fold like so:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
And as that evaluates:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (2, 2) [3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (3, 8) [4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (4, 20) []
(4, 20)
And then we throw away the 4 because we don't need it anymore and are just left with 20.
Your tir functions looks like a fold; in fact has the exact same type as List.fold_left:
# List.fold_left;;
- : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
In the following snippets the prod function looks like a map2
# List.map2;;
- : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
You can use a fold and a map to compute the function you want, but you also need first to build a list of indices from the list of values. You could do this as follows:
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t);;
For example:
# indices 1 [5;1;3];;
- : int list = [1; 2; 3]
This is not recursive terminal, if you first computed the length of the list, how would you build the list in a recursive terminal way?
Then you should be able to call prod on a list xs and on a secondary list indices 1 xs. It is a bit wasteful because you need to build an auxiliary list, but it looks quite simple to me to understand, higher-order functions like map or fold do work on whole lists so there are fewer corner cases to consider.
But, it might be better to first write a direct recursive function for your particular problem before going the more abstract route.
The direct recursive function also requires no additional memory allocation. If you write a recursive terminal function you'll carry additional accumulator values:
the current position in the list, initially 1
the current sum of products, initially 0
Then, your function has the following skeleton:
let rec f xs index product = match xs with
| [] -> ...
| h::t -> ...
You can wrap it in a main function g:
let g xs = f xs 1 0;;
Hello I'm trying to write a program in OCaml and was wondering if there is a way to get from list of pairs : [(1,2);(2,3);(3;5)] to a list where pairs are multiplied [2;6;15] this is what i have tried but it's giving me Exception: Failure "hd"
let rec mul l=
let x=(List.hd l) and y=(List.tl l) in
((fst x)*(snd x))::(mul y);;
mul [(3, 5); (3, 4); (3, 3);];;
What you want essentially is List.map (uncurry ( * )).
# let uncurry f (a, b) = f a b;;
val uncurry : ('a -> 'b -> 'c) -> 'a * 'b -> 'c = <fun>
# List.map (uncurry ( * )) [(3, 5); (3, 4); (3, 3);];;
- : int list = [15; 12; 9]
(uncurry is a basic FP function, but unfortunately it isn't defined in OCaml's fairly sparse standard library. But as you can see the definition is straightforward.)
To be honest, I think there must be simpler methods. Specifically, you have a list of n elements which are pairs (so a list of type (int * int) list) and you want to get a list of the same size, but which is the result of multiplying the two members of the pair. So, going from an (int * int) list to an int list.
As the objective is to preserve the size of the list, you can rephrase the statement by saying "I would like to apply a function on each element of my list". It is possible to do this manually, using, for example, pattern matching (which makes it possible to be explicit about the treatment of the empty list):
let rec mult my_list =
match my_list with
| [] -> (* case if my list is empty *)
[] (* The process is done! *)
| (a, b) :: tail -> (* if I have, at least, one element)
(a * b) :: (mult tail)
But generally, applying a function to each element of a list and preserving its size is called "mapping" (roughly), and fortunately there is a function in the standard OCaml library which allows this, and it is called, logically: List.map, here is its type: val map : ('a -> 'b) -> 'a list -> 'b list which could be translated as: give me a function which goes from 'a to 'b, a list of 'a and I can produce a list of 'b for you.
Here, we would like to be able to apply a function that goes from (int * int) -> int, for example: let prod (x, y) = x * y. So let's try to reimplement mult in terms of map:
let mult my_list =
let prod (x, y) = x * y in
List.map prod my_list
And voila, the pattern captured in the first purpose is exactly the idea behind List.map, for each element of a list, I apply a function and I keep the result of the function application.
Here is a working solution with the least amount of modification to your original code:
let rec mul l =
match l with
| [] -> [] (* <-- Deal with the base case *)
| _ -> (* Same as before --> *)
let x = (List.hd l) and y = (List.tl l) in
((fst x)*(snd x))::(mul y);;
Note that we just need to consider that happens when the list is empty, and we do that by matching on the list. The recursive case stays the same.
The question I have is how might I transform a list of a string and integer pair to a list of string and int list pairs.
For example, if I have the list [("hello",1) ; ("hi", 1) ; ("hello", 1) ; ("hi", 1) ; ("hey",1 )] then I should get back [("hello",[1;1]) ; ("hi", [1;1]) ; ("hey",[1])] where basically from a previous function I wrote that creates string * int pairs in a list, I want to group every string that's the same into a pair that has a list of ones of a length = to how many times that exact string appeared in a pair from the input list. Sorry if my wording is confusing but I am quite lost on this function. Below is the code I have written so far:
let transform5 (lst: (string *int) list) : (string *int list) list =
match lst with
| (hd,n)::(tl,n) -> let x,[o] = List.fold_left (fun (x,[o]) y -> if y = x then x,[o]#[1] else
(x,[o])::y,[o]) (hd,[o]) tl in (x,[1])::(tl,[1])
Any help is appreciated!
General advice on how to improve understanding of core concepts:
The code suggests you could use more practice with destructuring and manipulating lists. I recommend reading the chapter on Lists and Patterns in Real World Ocaml and spending some time working through the first 20 or so 99 OCaml Problems.
Some pointers on the code you've written so far:
I have reorganized your code into a strictly equivalent function, with some annotations indicating problem areas:
let transform5 : (string * int) list -> (string * int list) list =
fun lst ->
let f (x, [o]) y =
if y = x then (* The two branches of this conditional are values of different types *)
(x, [o] # [1]) (* : ('a * int list) *)
else
(x, [o]) :: (y, [o]) (* : ('a * int list) list *)
in
match lst with
| (hd, n) :: (tl, n) -> (* This will only match a list with two tuples *)
let x, [o] = List.fold_left f (hd, [o]) tl (* [o] can only match a singleton list *)
in (x, [1]) :: (tl, [1]) (* Doesn't use the value of o, so that info is lost*)
(* case analysis in match expressions should be exhaustive, but this omits
matches for, [], [_], and (_ :: _ :: _) *)
If you load your code in utop or compile it in a file, you should get a number of warnings and type errors that help indicate problem areas. You can learn a lot by taking up each of those messages one by one and working out what they are indicating.
Refactoring the problem
A solution to your problem using a fold over the input list is probably the right way to go. But writing solutions that use explicit recursion and break the task down into a number of sub-problems can often help study the problem and make the underlying mechanics very clear.
In general, a function of type 'a -> 'b can be understood as a problem:
Given a x : 'a, construct a y : 'b where ...
Our function has type (string * int) list -> (string * int list) list and you
state the problem quite clearly, but I've edited a bit to fit the format:
Given xs : (string * int) list, construct ys: (string * int list) list
where I want to group every string from xs that's the same into a pair
(string * int list) in ys that has a list of ones of a length = to how
many times that exact string appeared in a pair from xs.
We can break this into two sub-problems:
Given xs : (string * int) list, construct ys : (string * int) list list where each y : (string * int) list in ys is a group of the items in xs with the same string.
let rec group : (string * int) list -> (string * int) list list = function
| [] -> []
| x :: xs ->
let (grouped, rest) = List.partition (fun y -> y = x) xs in
(x :: grouped) :: group rest
Given xs : (string * int) list list, construct ys : (string * int list) list where for each group (string, int) list in xs we have one (s : string, n : int list) in ys where s is the string determining the group and n is a list holding all the 1s in the group.
let rec tally : (string * int) list list -> (string * int list) list = function
| [] -> []
| group :: xs ->
match group with
| [] -> tally xs (* This case shouldn't arise, but we match it to be complete *)
| (s, _) :: _ ->
let ones = List.map (fun (_, one) -> one) group in
(s, ones) :: tally xs
The solution to your initial problem will just be the composition of these two sub-problems:
let transform5 : (string * int) list -> (string * int list) list =
fun xs -> (tally (group xs))
Hopefully this is a helpful illustration of one way to go about decomposing these kinds of problems. However, there are some obvious defects with the code I have written: it is inefficient, in that it creates an intermediate data structure and it must iterate through the first list repeatedly to form its groups, before finally tallying up the results. It also resorts to explicit recursion, whereas it would be preferable to use higher order functions to take care of iterating over the lists for us (as you tried in your example). Trying to fix these defects might be instructive.
Reconsidering our context
Is the problem you've posed in this SO question the best sub-problem from the overall task you are pursuing? Here are two questions have occurred to me:
Why, do you have a (string * int) list where the value of int is always 1 in the first place? Does this actually carry any more information than a string list?
In general, we can represent any n : int by a int list which contains only 1s and has length = n. By why not just use n here?
I'm using SML recently and I'm trying to solve a problem.
I should create a function that accept an int list and return even int list,
I've already created it :
fun evens [] = [] |
evens [x] = [x] |
evens(x::xs) =
case x mod 2 of
0 => x::evens xs |
1 => evens xs;
which gives the correct result but I need to use foldr
this is what I came up with:
fun evens [] = [] |
evens(x::xs) =
case x mod 2 of
0 => foldr (op ::) evens xs [x] |
1 => evens xs;
but it is not working, I'm still confused with how to use foldr in this case.
any advice?
First of all, with foldr you should be looking for a 1-line definition rather than a recursive definition using patterns and cases. The point of foldr is that it incorporates a common recursion pattern -- you just need to use the pattern.
The type of foldr is
fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
In your case 'b is int list and 'a is int. The 'b between the arrows in the middle of foldr's type is the seed value. It typically corresponds to a basis value. When you are constructing lists this basis value is typically []. Thus -- you need to concentrate on the key question of what should be folded over the list. In other words -- what function of type ('a * 'b -> 'b) should you pass to foldr? In your case you need to pass a function of type
int * int list -> int list
this should be a function which, when given an int and an int list either tacks the int onto the list (if it is even) or leaves the list alone. You could define this function ahead of time, define it using let, or just use an anonymous function.
Under the assumption that this is homework, I don't want to give a complete answer, but here is a function which uses foldr to obtain the positive entries in a list:
fun positives xs =
foldr (fn (x,xs) => if x >= 0 then x::xs else xs) [] xs;
-
- positives [3,~2,4,5,0,~1,~1,5];
val it = [3,4,5,0,5] : int list