SML Function and Tuples - list

The SML function map takes a function and a list and it applies the function on the elements of the list.
The function map, which has the following type, is both polymorphic and higher order function.
fun map f [] = [] | map f (x::xs) = (f x)::(map f xs)
val it = fn : (’a -> ’b) -> ’a list -> ’b list
Write another function mymap that takes two functions f and g and a list of 2-element tuples.
It applies f on the first element of the tuples and it applies g on the second element of the tuples.
For example:
- fun sqr x = x* x;
val sqr = fn : int -> int
- fun cube x:real = x*x*x;
val cube = fn : real -> real
- mymap sqr cube [(1,2.0),(2,3.0),(3,4.0),(4,5.0)];
I don't know how to used first function map and i need hint for second function mymap

You could try:
fun mymap f g l =
let
fun f1 f (h,h1) = (f(h),h1)
fun g1 g (h,h1) = (h,g(h1))
in
map (g1 g) (map (f1 f) l)
end
We define two functions f1,g1 which have tuple as argument so that we could use map with f1 and list of tuples and same for g1.
Example:
- mymap sqr sqr [(4,9),(4,16),(9,4)];
val it = [(16,81),(16,256),(81,16)] : (int * int) list

Related

How can you make a function that returns a function in ocaml

for an example, if a function receives a function as a factor and iterates it twice
func x = f(f(x))
I have totally no idea of how the code should be written
You just pass the function as a value. E.g.:
let apply_twice f x = f (f x)
should do what you expect. We can try it out by testing on the command line:
utop # apply_twice ((+) 1) 100
- : int = 102
The (+) 1 term is the function that adds one to a number (you could also write it as (fun x -> 1 + x)). Also remember that a function in OCaml does not need to be evaluated with all its parameters. If you evaluate apply_twice only with the function you receive a new function that can be evaluated on a number:
utop # let add_two = apply_twice ((+) 1) ;;
val add_two : int -> int = <fun>
utop # add_two 1000;;
- : int = 1002
To provide a better understanding: In OCaml, functions are first-class
values. Just like int is a value, 'a -> 'a -> 'a is a value (I
suppose you are familiar with function signatures). So, how do you
implement a function that returns a function? Well, let's rephrase it:
As functions = values in OCaml, we could phrase your question in three
different forms:
[1] a function that returns a function
[2] a function that returns a value
[3] a value that returns a value
Note that those are all equivalent; I just changed terms.
[2] is probably the most intuitive one for you.
First, let's look at how OCaml evaluates functions (concrete example):
let sum x y = x + y
(val sum: int -> int -> int = <fun>)
f takes in two int's and returns an int (Intuitively speaking, a
functional value is a value, that can evaluate further if you provide
values). This is the reason you can do stuff like this:
let partial_sum = sum 2
(int -> int = <fun>)
let total_sum = partial_sum 3 (equivalent to: let total_sum y = 3 + y)
(int = 5)
partial_sum is a function, that takes in only one int and returns
another int. So we already provided one argument of the function,
now one is still missing, so it's still a functional value. If that is
still not clear, look into it more. (Hint: f x = x is equivalent to
f = fun x -> x) Let's come back to your question. The simplest
function, that returns a function is the function itself:
let f x = x
(val f:'a -> 'a = <fun>)
f
('a -> 'a = <fun>)
let f x = x Calling f without arguments returns f itself. Say you
wanted to concatenate two functions, so f o g, or f(g(x)):
let g x = (* do something *)
(val g: 'a -> 'b)
let f x = (* do something *)
(val f: 'a -> 'b)
let f_g f g x = f (g x)
(val f_g: ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>)
('a -> 'b): that's f, ('c -> 'a): that's g, c: that's x.
Exercise: Think about why the particular signatures have to be like that. Because let f_g f g x = f (g x) is equivalent to let f_g = fun f -> fun g -> fun x -> f (g x), and we do not provide
the argument x, we have created a function concatenation. Play around
with providing partial arguments, look at the signature, and there
will be nothing magical about functions returning functions; or:
functions returning values.

High order SML questions

So, I am trying to create a high order SML function that takes in a number and returns all the functions and returns its factors. I have done questions where I would take a list of values and return the values that are divisible but I never did anything like take a number and make a list out of it. Following the question:
Define a function factorize = fn: int -> int list that takes an integer and returns all its factors in a list. For example, factorize 12 will return [1, 2, 3, 4, 6, 12].
The second one is a tricky one, I couldn't understand how its done so dropping it here. I would appreciate any help I get on this one.
Define a function cfoldl that behaves exactly same as the standard foldl except that the type of the function argument does not take a 2-tuple’ instead, the input function should use the currying notation as is ’a -> ’b -> ’b. Thus, the type of cfoldl should be fn : (’a -> b -> ’b) -> ’b -> ’a list -> ’b. For example, cfoldl (fn a => fn b => a-b) 1 [1,2,3,4]; will return 3.
I made this for the foldl:
fun cfoldl f b [] = b
| cfoldl f b (x::xs) = cfoldl f (f (x, b)) xs;
Thank you!
factorize = fn: int -> int list that takes an integer and returns all its factors in a list
Here's a recursive function that takes a number and generates a list of numbers from 1 up to that number:
fun upto n =
let fun go i = if i < n
then i :: go (i+1)
else []
in go 1
end
Could you make a function isFactor x y that is true when x is a factor of y?
If you had such a function, could you modify the above function to make use of it?
a function cfoldl that should use the currying notation as is ’a -> ’b -> ’b
fun cfoldl f b [] = b | cfoldl f b (x::xs) = cfoldl f (f (x, b)) xs;
This is exactly foldl.
fun foldl f e [] = e
| foldl f e (x::xr) = foldl f (f(x, e)) xr;
Here, f : ('a * 'b) -> 'b because f is being used as f(x, e), so naturally it will assume a tuple. You can change the inferred type of f by using it differently.
Can you think of a way where f : 'a -> 'b -> 'b?

Multiplying Lists through Folding

So I am currently trying to figure out how to write a function where it takes 2 lists of equal lengths and multiplies the same position of both lists through folding, and returns the result as a new List.
eg) let prodList [1; 2; 3] [4; 5; 6] ;;
==> (through folding) ==> [1*4; 2*5; 3*6]
==> result = [4; 10; 18]
I feel like I need to use List.combine, since it will put the values that need to be multiplied into tuples. After that, I can't figure out how to break apart the tuple in a way that allows me to multiply the values. Here is what I have so far:
let prodLists l1 l2 =
let f a x = (List.hd(x)) :: a in
let base = [] in
let args = List.rev (List.combine l1 l2) in
List.fold_left f base args
Am I on the right track?
You can use fold_left2 which folds two lists of the same length. The documentation can give you more details (https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html):
val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
List.fold_left2 f a [b1; ...; bn] [c1; ...; cn] is f (... (f (f a b1 c1) b2 c2) ...) bn cn. Raise Invalid_argument if the two lists are determined to have different lengths.
Another way is to fold the output of combine as you have suggested, I would recommend you to try it by yourself before looking at the solution bellow.
Solution:
let prod_lists l s =
List.rev (List.fold_left2 (fun acc a b -> (a * b) :: acc) [] l s);;
let prod_lists' l s =
List.fold_left (fun acc (a, b) -> (a * b) :: acc) [] (List.rev (List.combine l s));;
First let me note using fold to implement this operation seems a bit forced, since you have to traverse both lists at the same time. Fold however combines the elements of a single list. Nonetheless here is an implementation.
let e [] = []
let f x hxs (y::ys) = (x*y) :: hxs ys
let prodList xs ys = List.fold_right f xs e ys
Looks a bit complicated, so let me explain.
Universal Property of fold right
First you should be aware of the following property of fold_right.
h xs = fold_right f xs e
if and only if
h [] = e
h (x::xs) = f x (h xs)
This means that if we write the multiplication of lists in the recursive form below, then we can use the e and f to write it using fold as above. Note though we are operating two lists so h takes two arguments.
Base case - empty lists
Multiplying two empty lists returns an empty list.
h [] [] = []
How to write this in the form above? Just abstract over the second argument.
h [] = fun [] -> []
So,
e = fun [] -> []`
Or equivalently,
e [] = []
Recursive case - non-empty lists
h (x::xs) (y::ys) = x*y :: h xs ys
Or, using just one argument,
h (x::xs) = fun -> (y::ys) -> x*y :: h xs ys
Now we need to rewrite this expression in the form h (x::xs) = f x (h xs). It may seem complicated but we just need to abstract over x and h xs.
h (x::xs) = (fun x hxs -> fun (y::ys) -> x*y :: hxs ys) x (h xs)
so we have that f is defined by,
f = fun x hxs -> fun (y::ys) -> x*y :: hxs ys
or equivalently,
f x hxs (y::ys) = x*y :: hxs ys
Solution as a fold right
Having determined both e and f we just plug then into fold according to the first equation of the property above. And we get,
h xs = List.fold_right f xs e
or equivalently,
h xs ys = List.fold_right f xs e ys
Understanding the implementation
Note that the type of List.fold_right f xs e is int list -> int list, so the fold is building a function on lists, that given some ys will multiply it with the given parameter xs.
For an empty xs you will expect an empty ys and return an empty result so,
e [] = fun [] -> []
As for the recursive case, the function f in a fold_right must implement a solution for x::xs from a solution for xs. So f takes an x of type int and a function hxs of type int list -> int list which implements the multiplication for the tail, and it must implement multiplication for x::xs.
f x hxs = fun (y::ys) -> x*y :: hxs ys
So f constructs a function that multiplies x with y, and then applies to ys the already constructed hxs which multiplies xs to a list.
You mostly have the right idea; you'll want to combine (zip in other languages) the two lists and then map over each tuple:
let prod_lists l1 l2 =
List.combine l1 l2
|> List.map (fun (a, b) -> a * b)
The key is that you can pattern match on that tuple using (a, b).
You can also fold over the combined list, then rev the result, if you don't want to use map.

How do I use List.map to apply a function on a int list list?

Suppose I have a (int list list) x = [[1;1;1]; [2;2;2]; [3;4;5]] and a function f. The result should be [f [1;1;1]; f [2;2;2]; f[3;4;5]]. The built in List.map works only for int list but not for int list list.The i-th entry in this new column is computed by the function f which is taking as input the i-th element from each column in the spreadsheet and forms a new element.
let newList x f = List.map f x (* this is the only map function that I know *)
You can use List.map f as a function, which works on one dimensional lists, and then map that function on the two-dimensional list as follows:
let x = [[1;1;1]; [2;2;2]; [3;4;5]];;
let f x = x + 1;;
List.map (List.map f) x;;
output:
- : int list list = [[2; 2; 2]; [3; 3; 3]; [4; 5; 6]]
my function will take as input two arguments, an int list list and a
function f. It will output a new int list. Input = m = [[x1;x2;x3] ;
[y1;y2;y3] ; [z1;z2;z3]] and function f Output = [f [x1;y1;z1] ; f
[x2;y2;z2] ; f [x3;y3;z3]]
It seems that you wanted to transpose (https://stackoverflow.com/a/3989823/4196578) your 2-D array and then map f. In that case, you can do:
let rec transpose list = match list with
| [] -> []
| [] :: xss -> transpose xss
| (x::xs) :: xss ->
(x :: List.map List.hd xss) :: transpose (xs :: List.map List.tl xss);;
let myfunc m f = List.map f (transpose m);;

How to use List.filter?

I have this code to filter list of string that the first letter is capital:
fun f s = Char.isUpper(String.sub(s,0));
fun only_capitals (xs : string list) = List.filter(f , xs);
But when compile, I always receive error :
operator domain: 'Z -> bool
operand: (string -> bool) * string list
in expression:
List.filter (f,xs)
What does this error mean? How to fix it?
Type signature of List.filter is
val filter : ('a -> bool) -> 'a list -> 'a list
So you need to give List.filter two distinct arguments, not one argument which happens to be a tuple.
You need to change it to:
fun only_capitals (xs : string list) = List.filter f xs
filter takes 2 arguments, a function f ('a -> bool) and a list.
It's easy to confuse syntax of passing a tuple in ML with the sytax of functional application in other languages.
You could also define it as:
val only_capitals = List.filter f
Functions in ML can take only one argument. Description from here (see also notes and video there).
List.filter is so called curried function, so List.filter f xs is actually (List.filter f) xs where List.filter f is a function. We have to provide f (fn: a -> bool) as an argument to List.filter, not tuple (f, xs).
Here is a simple example. When we call is_sorted 1 we get a closure with x in its environment. When we call this closure with 2 we get true because 1 <= 2.
val is_sorted = fn x => (fn y => x <= y)
val test0 = (is_sorted 1) 2
val is_sorted = fn : int -> int -> bool
val test0 = true : bool
In the SML document, it states that:
filter f l
applies f to each element x of l, from left to right, and returns the list of those x for which f x evaluated to true, in the same order as they occurred in the argument list.
So it is a curried function.
In the SML document, the filter function in the List structure listed as
filter f l
where it takes curried arguments f and l
Instead of passing the arguments in a tuple, you have to provide a function and the list separated by spaces. The answer will be like this
fun only_capitals (xs: string list) =
List.filter (fn s => Char.isUpper(String.sub(s,0))) xs