I have to write a function to print a list in SML with the following type signature :
val printGenList = fn : ('a -> 'b) -> 'a list -> unit
The "printGenList" will take two arguments function f and list l and applies the function f to each element of list l recursively.
Since I am new to ML, I am not able to implement it but I tried this code which is giving the different type signature
fun printGenList = CONS(fib, fn => printGenList fib fibs);
where, fib is
fun fib a b = CONS(a, fn => fib b (a+b));
and fibs is
val fibs = fib 0 1;
What you're trying to do is impossible, ML's type system doesn't support this type of polymorphism. If you Google, there are some printf libraries for SML that show you how to approach this -- for each type t that you want to print, you'll need to define a separate t -> unit function and compose them together.
EDIT: Oh, I see, you're not looking for a function to print lists of any type, you're looking for a higher order function that applies an 'a->'b function to every element of a list... my mistake. This is what you need:
val rec printGenList =
fn (f : 'a -> 'b) =>
(fn [] => ()
| x::xs => (f(x); printGenList f xs))
Related
I know List.map uses recursion, I'm just wondering if there's a simpler way to implement map function without using recursion.
I know for reverse, I can simplify it into:
(* given *)
type 'a list =
| []
| (::) of 'a * 'a list
let nil : 'a list = []
let cons (hd : 'a) (tl : 'a list): 'a list = hd :: tl
let reverse (ls : 'a list): 'a list =
List.fold_left (Fun.flip cons) [] ls
Right now I'm thinking about using ##(the application operator), %(the function composition operator), and maybe Fun.flip or List.fold_left to do it, can anyone give me some hint about that?
I have tried the following, but OCaml raised an error about it.
List.fold_left (fun x -> f x) [] ls
List.fold_left uses recursion, so presumably you're looking to avoid use of the rec keyword, rather than recursion at all.
You note in comments trying:
List.fold_left (fun x -> f x) [] ls
But the function passed to List.fold_left must take two arguments: the initial state, and the first element of the list. Fun.flip cons worked in your reverse function because it does take two arguments.
Note: fun x -> f x is the same as writing f.
If you initial state is a list, you need to do something to that list in the function you pass to List.fold_left, like adding the result of f x to the front of it. Since this builds the list backwards, you will need to reverse the result. This is where ## will come in handy.
let map f lst =
List.(
rev ## fold_left (fun i x -> f x :: i) [] lst
)
I am trying to understand difference between these two;
val my_fun = length o List.filter (fn (item) => item = #"a") o String.explode
This one can be invoked (my_fun "name" will return 1) and works fine. I am trying to understand why following is not working
length o (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
Definition of function composition in sml
f o g = f(g(x))
In the second form what we do is ( I think)
length ([#"a"])
You seem to be confusing function composition with function application.
Composition is a higher-order function which takes two functions, f and g, of compatible types and returns another function -- the function which is computed by first applying the g to a value and then applying f to the result. o is a built-in operator, but if you wanted to define composition yourself it would be something like
fun compose (f,g) x = f(g(x))
this has type fn : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b (which is exactly the type you get when you type (op o); in the REPL). Note that the return value of compose is 'c -> 'b, which is a function type.
length o List.filter (fn (item) => item = #"a") o String.explode
makes perfect sense since the types are compatible and composition is right-associative.
On the other hand, as you already note,
length o (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
would be equivalent to
length o [#"a"]
That really doesn't make sense. What would it even mean to compose a function with a list. A list isn't a function. It does make sense to apply length to that list, which is what you seem to expect.
Application is simply juxtaposition, so all you would need to do is write
length (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
Which reduces to length [#"a"] and from thence to 1.
If you wanted to write your own apply function you would write:
def apply f x = f x
This might strike you as superficially similar to compose but its type is radically different: fn : ('a -> 'b) -> 'a -> 'b. Composition involves application, but it isn't the same thing.
I have to write a function to remove elements from a lazy list. Indexes of elements to be removed are in list xs.
I don't know where I should sort xs? When I try in this way I get "Error: This expression has type...".
type 'a llist = LNil | LCons of 'a * (unit -> 'a llist)
let rec remove xs ll =
let rec helper =
function
| (_, i, LNil) -> LNil
| (h::t, i, LCons(x, xf)) -> if h = i then helper (t, (i + 1), xf())
else LCons(x, fun() -> helper (h::t, (i + 1), xf()))
| ([], i, LCons(x, xf)) -> LCons(x, xf)
in helper (List.sort xs, 0, ll);;
List.sort from OCaml standard library has the following interface:
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
That means, that it accepts a function and a list. The function should have type 'a -> 'a -> int, i.e., it takes two elements of arbitrary type 'a and returns a value of type int that defines the mutual order of the arguments. The second argument is a list of values, where each value has type 'a. A usual invocation of the sort function is:
List.sort compare [2;1;4;3]
So with this knowledge we can tackle with your program:
You invoke List.sort on xs this has two consequences:
type inference system concludes that xs is a function of type 'a -> 'a -> int.
The result of List.sort xs is a function of type 'a list -> 'a list. This is because, List.sort requires two arguments, but you provided only one.
(List.sort xs) is a function that takes a list & returns a list - as xs is supposed to be the function that sorts the element of the list; you miss to pass a list as arg.
...whereas a list is expected.
I need to find a way to combine two functions and output them as one.
I have the following code where take in a list of function ('a->'a) list then output a function ('a->'a) using the List.fold_left.
I figured out the base case, but I tried a lot of ways to combine two functions. The output should have the type ('a -> 'a) list -> ('a -> 'a).
example output:
# pipe [] 3;;
- : int = 3
# pipe [(fun x-> 2*x);(fun x -> x + 3)] 3 ;;
- : int = 9
# pipe [(fun x -> x + 3);(fun x-> 2*x)] 3;;
- : int = 12
function:
let p l =
let f acc x = fun y-> fun x->acc in (* acc & x are functions 'a->'a *)
let base = fun x->x in
List.fold_left f base l
Since you know that you have to use a left fold, you now have to solve a fairly constrained problem: given two functions of type 'a -> 'a, how do you combine them into a single function of the same type?
In practice, there is one general way of combining functions: composition. In math, this is usually written as f ∘ g where f and g are the functions. This operation produces a new function which corresponds to taking an argument, applying g to it and then applying f to the result. So if h = f ∘ g, then we can also write this as h(x) = f(g(x)).
So your function f is actually function composition. (You should really give it a better name than f.) It has to take in two functions of type 'a -> 'a and produce another function of the same type. This means it produces a function of one argument where you produce a function taking two arguments.
So you need to write a function compose (a more readable name than f) of type ('a -> 'a) -> ('a -> 'a) -> ('a -> 'a). It has to take two arguments f and g and produce a function that applies both of them to its argument.
I hope this clarifies what you need to do. Figuring out exactly how to do it in OCaml is a healthy exercise.
Write an Ocaml function list_print : string list -> unit that prints all the strings in a list from left to right:
So Lets say I've got an Ocaml function list_print: string list -> unit that prints all the strings in a list from left to write. Now the correct solution is:
let list_print lst = List.fold_left (fun ( ) -> fun s -> print_string s) () lst;;
But When writing my solution, I wrote it as such:
let list_print lst = List.fold_left (fun s -> print_string s) () lst;;
But this gave me
Error: This expression has type unit but an expression was expected of type 'a -> string
Why is it that I need that first parameter fun() -> before the fun s? I'm still new to Ocaml so this type system is quite confusing to me
The purpose of fold_left (and fold_right) is to accumulate a value as you go along. The extra parameter is this accumulated value.
You can use List.iter for your problem. It doesn't accumulate a value.
You could think of List.iter as a version of List.fold_left that accumulates values of type unit. And, in fact, you could implement it that way:
let iter f = List.fold_left (fun () a -> f a) ()
The point (as always with unit) is that there's only one value of the type, so it represents cases where the value isn't interesting.
You want to use List.fold_left, that's fine, but you should start by reading the documentation for that function. The official documentation is quite short:
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
List.fold_left f a [b1; ...; bn] is f (... (f (f a b1) b2) ...) bn.
The first thing is the type of that function. The type is
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
In other words, the function fold_left has three arguments and one result value. The first argument has type ('a -> 'b -> 'a). The second argument has type 'a. The third argument has type 'b list. The result value of the function has type 'a.
Now, in your case, you want to print the strings. So you do not actually need any result value, you need a side effect. However, in OCaml all functions must have a result value. So you use the empty value, (), which has type unit. Therefore, the type parameter 'a will be equal to unit in your case.
The type parameter 'b is string because you are required to work on the list of strings.
Therefore, in your case the function fold_left must have the type
(unit -> string -> unit) -> unit -> string list -> unit.
The first argument of fold_left must have the type unit->string->unit. In other words, it must be a function with two arguments, first argument is the empty value, i.e. (), the second argument a string. So the first argument to fold_left must be a function of this kind,
fun x y -> ...
where x must be of type unit and y of type string. Since x is going to be always equal to (), it is not necessary to write this argument as a variable x, instead we can simply write () or even the dummy argument _. (The syntax fun x -> fun y -> ... gives the same function as fun x y -> ....)
Now you can begin to figure out how fold_left works. Since this is obviously a homework question, I will leave this task to you.