Why is this function curried? - sml

To my understanding, curried functions should always return a function. However, in the code below, I believe this function returns a list. But when I check the type, it looks like a curried function.
fun zipWith f xs ys =
case (xs,ys) of
([],_) => []
| (_,[]) => []
| (x::xs',y::ys') => (f(x,y)) :: zipWith f xs' ys'
The type:
val zipWith = fn : ('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list.
Could someone explain the type and how currying works in this function. Any help is appreciated!

fun f arg1 ... argN = exp is a syntactic shortcut for val rec f = fn arg1 => ... => fn argN => exp. So in your case we have:
val rec zipWith = fn f => fn xs => fn ys =>
case (xs, ys) of
...
So zipWith is a function that, when given an argument f, returns another function that, when given an argument xs, ... and so on. In other words, it's curried.

It is curried - you don't need to pass all the arguments at once, but it produces a list when all of them have "arrived".
It's common to write all the curried parameters on the left-hand side if the function is not meant to be primarily a "function-creating" function.
The definition looks more like the type if you write it on the (equivalent) form
fun zipWith f = fn xs =>
fn ys =>
case (xs,ys) of
([],_) => []
| (_,[]) => []
| (x::xs',y::ys') => (f(x,y)) :: ((zipWith f) xs') ys'
Example of the "curriedness":
- val add = zipWith (op +);
val add = fn : int list -> int list -> int list
- val add_123 = add [1,2,3];
val add_123 = fn : int list -> int list
- add_123 [4,5,6];
val it = [5,7,9] : int list

Related

List.assoc using List.find

I want to implement the List.assoc function using List.find, this is what I have tried:
let rec assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> try (List.find (fun x -> a = x) lista)
b
with Not_found -> assoc l x;;
but it gives me this error:
This expression has type ('a * 'b) list but an expression was expected of type 'a list
The type variable 'a occurs inside 'a * 'b
I don't know if this is something expected to happen or if I'm doing something wrong. I also tried this as an alternative:
let assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> match List.split lista with
| (l1,l2) -> let ind = find l1 (List.find (fun s -> compare a x = 0))
in List.nth l2 ind;;
where find is a function that returns the index of the element requested:
let rec find lst x =
match lst with
| [] -> raise Not_found
| h :: t -> if x = h then 0 else 1 + find t x;;
with this code the problem is that the function should have type ('a * 'b) list -> 'a -> 'b, but instead it's (('a list -> 'a) * 'b) list -> ('a list -> 'a) -> 'b, so when I try
assoc [(1,a);(2,b);(3,c)] 2;;
I get:
This expression has type int but an expression was expected of type
'a list -> 'a (refering to the first element of the pair inside the list)
I don't understand why I don't get the expected function type.
First off, a quick suggestion on making your assoc function more idiomatic OCaml: have it take the list as the last argument.
Secondly, why are you attempting to implement this in terms of find? It's much easier without.
let rec assoc x lista =
match lista with
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
Something like this is simpler and substantially more efficient with the way lists work in OCaml.
Having the list as the last argument, even means we can write this more tersely.
let rec assoc x =
function
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
As to your question, OCaml infers the types of functions from how they're used.
find l1 (List.find (fun s -> compare a x = 0))
We know l1 is an int list. So we must be trying to find it in an int list list. So:
List.find (fun s -> compare a x = 0)
Must return an int list list. It's a mess. Try rethinking your function and you'll end up with something much easier to reason about.

Filter function in SML

I use this function to filter a list of integers. I'm beggining in SML and I don't know where is the error.
fun filter f = fn [] => []
| fn (x::xs) => if f(x)
then x::(filter f xs) else (filter f xs)
fun g(x) = if x>5 then true else false
val listTest = filter g [1, 2, 4, 6, 8, 10]
Thank you!
Definitions with fn look like definitions with fun, but without the name and an arrow instead of =:
fn a0 => e0
| a1 => e1
| ...
This would be correct:
fun filter f = fn [] => []
| (x::xs) => if f(x)
then x::(filter f xs)
else (filter f xs)
but the common form is
fun filter _ [] = []
| filter f (x::xs) = if f x
then x :: filter f xs
else filter f xs
fun g x = x > 5
You second fn is redundant, please remove it:
fun filter f = fn [] => []
| (x::xs) => if f(x)
then x::(filter f xs) else (filter f xs)
Then it can compile happily:
- use "a.sml";
[opening a.sml]
val filter = fn : ('a -> bool) -> 'a list -> 'a list
val g = fn : int -> bool
val listTest = [6,8,10] : int list
val it = () : unit
BTW, fun g(x) = if x>5 then true else false is not good style. fun g x = x > 5 is better

iterate with fold_right in Ocaml

fold_right gives me values starting from the tail of the list but I want to give a function to fold_right as a parameter such that this function would collect values starting from the head of the list .
I want iterto receive values starting with the head of the list.
Continous Passing is the keyword ... .Another way to ask the question would be how tofold_leftwith fold_right
let fold f ls acc = List.fold_right f ls acc
val iter : ('a -> unit) -> 'a t -> unit
let iter f my_type =
let rec iiter my_type return =
return (fold (fun x y -> f x) my_type ()) () in iiter my_type (fun x y -> ())
But when I call :
iter (fun a -> print_string a) ["hi";"how";"are";"you"];;
Output:
youarehowhi
I need
hihowareyou
This is quite simple, you must try to match the signatures for the behavior.
Iteration takes no input, and returns unit, while folding takes an input and returns an output of the same type. Now, if the input taken by folding is unit then you'll have a folding function which applies a function on each element of a collection by passing an additional unit and returning an unit, which basically corresponds to the normal iteration, eg:
# let foo = [1;2;3;4;5];;
# List.fold_left (fun _ a -> print_int a; ()) () foo;;
12345- : unit = ()
As you can see the fold function just ignores the first argument, and always returns unit.
let fold_left f init ls =
let res = List.fold_right (fun a b acc -> b (f acc a)) ls (fun a -> a)
in res init
now calling
fold_left (fun a b -> Printf.printf "%s\n" b) () ["how";"are";"you"];;
gives us
how
are
you
fold_left is like List.fold_left but constructed with List.fold_right (Not tail-recursive):
let fold_left f a l = List.fold_right (fun b a -> f a b) (List.rev l) a ;;
Is not a good idea, because fold_left is not tail-recursive and List.fold_left is tail-recursive. Is better to produce a fold_right (tail-recursive) as :
let fold_right f l a = List.fold_left (fun a b -> f b a) a (List.rev l) ;;
If you can't use List.rev :
let rev l =
let rec aux acc = function
| [] -> acc
| a::tl -> aux (a::acc) tl
in
aux [] l
;;
iter use fold_left :
let iter f op = ignore (fold_left (fun a b -> f b;a) [] op ) ;;
Test :
# fold_left (fun a b -> (int_of_string b)::a ) [] ["1";"3"];;
- : int list = [3; 1]
# rev [1;2;3];;
- : int list = [3; 2; 1]
# iter print_string ["hi";"how";"are";"you"];;
hihowareyou- : unit = ()
The continuation that you need to pass through fold in this case is a function that will, once called, iterate through the rest of the list.
EDIT: like so:
let iter f list = fold
(fun head iter_tail -> (fun () -> f head;; iter_tail ()))
list
()

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

How can I skip a term with List.Map in OCAML?

Suppose I have some code like this:
List.map (fun e -> if (e <> 1) then e + 1 else (*add nothing to the list*))
Is there a way to do this? If so, how?
I want to both manipulate the item if it matches some criteria and ignore it if it does not. Thus List.filter wouldn't seem to be the solution.
SML has a function mapPartial which does exactly this. Sadly this function does not exist in OCaml. However you can easily define it yourself like this:
let map_partial f xs =
let prepend_option x xs = match x with
| None -> xs
| Some x -> x :: xs in
List.rev (List.fold_left (fun acc x -> prepend_option (f x) acc) [] xs)
Usage:
map_partial (fun x -> if x <> 1 then Some (x+1) else None) [0;1;2;3]
will return [1;3;4].
Or you can use filter_map from extlib as ygrek pointed out.
Both Batteries and Extlib provide an equivalent of mapPartial: their extended List module sprovide a filter_map function of the type ('a -> 'b option) -> 'a list -> 'b list, allowing the map function to select items as well.
Another solution would be to use directly a foldl :
let f e l = if (e <> 1)
then (e + 1)::l
else l
in List.fold_left f [] list
But my preference is filter_map as Michael Ekstrand provided
Alternatively you can filter your list then apply the map on the resulted list as follows :
let map_bis predicate map_function lst =
List.map map_function (List.filter predicate lst);;
# val map_bis : ('a -> bool) -> ('a -> 'b) -> 'a list -> 'b list = <fun>
Usage :
# map_bis (fun e -> e<>1) (fun e -> e+1) [0;1;2;3];;
- : int list = [1; 3; 4]
You can also map values to singleton lists if you want to keep them or empty lists if you don't, and then concat the results.
List.concat (List.map (fun e -> if (e <> 1) then [e + 1] else []) my_list)
use
let rec process = function
| 1 :: t -> process t
| h :: t -> (h + 1) :: (process t)
| [] -> []
or tail recursive
let process =
let rec f acc = function
| 1 :: t -> f acc t
| h :: t -> f ((h + 1) :: acc) t
| [] -> List.rev acc in
f []
or with a composition of standard functions
let process l =
l |> List.filter ((<>)1)
|> List.map ((+)1)
The OCaml standard library has had List.filter_map since 4.08. This can therefore now be written as:
List.filter_map (fun e -> if e <> 1 then Some (e + 1) else None)