List reverse Ocaml - functional-programming

I'm creating a function that reverse a list.
I think all is good but the compiler isn't of the same opinion...
This is the code :
let reverse list_ =
let rec support list_ =
match list_ with
| [] -> []
| hd :: tl -> support tl :: hd in
let return = support list_ in return
The error is :
| hd :: tl -> support tl :: hd in
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list`
My idea is to reach the end of the list than I'll build a new list from [] adding the latest elements.

The operator :: is not symmetric. It takes a list element at the left and a list at the right. In this expression:
support tl :: hd
You have a list at the left (the result of the recursive call) and a list element at the right. So that's not going to work.

The error is telling you that support tl has type 'a list while the :: operator works like this: 1 :: [2;3] = [1;2;3]. Conceptually what you are trying to do is [3; 2] :: 1, which is not how the operator works.
If you want to append hd at the end of a list you need to use the # operator (or the append function):
let reverse list_ =
let rec support list_ =
match list_ with
| [] -> []
| hd :: tl -> support tl # [hd] in
let return = support list_ in return
Now the problem is time complexity, we are iterating through the entire list for each element. To deal with this we can use a list on which we accumulate the elements:
let reverse list =
let rec support acc list_ =
match list_ with
| [] -> acc
| hd :: tl -> support (hd :: acc) tl in
let return = support [] list in return
This code could be rewritten a bit considering that:
the expression let return = support [] list in return is the same as support [] list
let some_fun some_val = match some_val with (* ... *) can be written as let some_fun = function (* ... *) omitting some_val entirely
let reverse list =
let rec support acc = function
| [] -> acc
| hd :: tl -> support (hd :: acc) tl in
support [] list
I guess that using match or function is just a matter of personal preference though.

Related

Why this function has weak type when i use function keyword? OCaml

let duplicates =
let rec duplicates' accumulator = function
| [] -> accumulator
| [ item ] -> duplicates' (item :: accumulator) []
| item :: item2 :: tail ->
if item = item2 then duplicates' (item :: accumulator) tail
else duplicates' (item::accumulator) (item2::tail)
in
duplicates' [];;
If I add a second parameter that must be a 'a list and use "match with" on it the code works.
(also: the end of codes and with: in duplicates [] 'parameter')
If I use function keyword and make the code more concise, the function returns:
val duplicates : '_weak14 list -> '_weak14 list = <fun>
This is the value restriction. Your function duplicates is defined not by a value (i.e., a lambda) but as an application: duplicates' []. So it can't be generalized.
You can fix this using eta expansion:
# let duplicates list =
let rec duplicates' accumulator = function
| [] -> accumulator
| [ item ] -> duplicates' (item :: accumulator) []
| item :: item2 :: tail ->
if item = item2 then duplicates' (item :: accumulator) tail
else duplicates' (item::accumulator) (item2::tail)
in
duplicates' [] list ;;
val duplicates : 'a list -> 'a list = <fun>
#
This works because duplicates is now defined as a lambda using the compact notation let f x = e, equivalent to let f = fun x -> e.
The value restriction is documented in Section 6 of the OCaml manual, "Polymorphism and its limitations."
I've found the following paper extremely helpful in thinking about the value restriction: Garrigue, Jacques; Relaxing the Value Restriction.

How do I make a function in OCaml that takes in a list and a predicate and then returns the elements that don't satisfy the predicate?

As the title suggests, I want to write a function that takes in an 'a list and an expression that evaluates to either true or false when elements of the list are passed into it. The function should return an 'a list of all the elements that don't satisfy the predicate given. The type should be
'a list -> ('a -> bool) -> 'a list
when it is working properly.
This is what I have so far,
let rec filter (x: 'a list) pred =
if x = [] then [] else
if x -> pred = true then remove_if (x.tl) pred else
x :: xs remove_if (x.tl) pred ;;
I tried some other ways of writing it but in my closest attempt the type ended up evaluating improperly.
Here's something to get you started..
let rec filter f lst =
match lst with
| [] -> []
| hd::tl ->
if (f hd)
(*The rest of the function goes here*)

how to insert in the middle of a list, being tail-call friendly but without hurting performance?

So I have this function which seems to be non-tail-call friendly, right?
let rec insertFooInProperPosition (foo: Foo) (bar: list<Foo>): list<Foo> =
match bar with
| [] -> [ foo ]
| head::tail ->
if (foo.Compare(head)) then
foo::bar
else
head::(insertFooInProperPosition foo tail)
Then I try to figure out how to use an accumulator so that the last thing done by the function is call itself, and I come up with this:
let rec insertFooInProperPositionTailRec (foo: Foo) (headListAcc: list<Foo>) (bar: list<Foo>): list<Foo> =
match bar with
| [] -> List.concat [headListAcc;[ foo ]]
| head::tail ->
if (foo.Compare(head)) then
List.concat [headListAcc; foo::bar]
else
insertFooInProperPosition foo (List.concat [headListAcc;[head]]) tail
let rec insertFooInProperPosition (foo: Foo) (bar: list<Foo>): list<Foo> =
insertFooInProperPositionTailRec foo [] bar
However, as far as I understand, the usage of List.concat would make this function much less efficient, right? So then how would I go and do this conversion properly?
Your solution looks ok if using recursion is required. However, the this task can be achieved without recursion (and a bit faster).
To concatenate two lists the first list should be copied and its last element should point to the first element of the second list. This is O(N) where N is the size of the first list. Growing list at the tail requires multiple concatenations, resulting traversing list for each N, which makes the complexity quadratic (hope I right here).
Instead of recursive approach that adds items to the list, the faster approach would be probably to find the insertion index and then copy all the items before it in one go and then concat it with new item and the rest of the list. This requires only three passes through the list so O(N).
let insertFooInProperPosition (foo : Foo) (bar : Foo list) : Foo list =
bar
|> List.tryFindIndex (fun v -> v.Compare foo)
|> function | None -> List.append bar [ foo ]
| Some i -> let before, after = List.splitAt i bar
List.concat [ before; [ foo ]; after ]
Unfortunately you cannot build up an F# list from head to tail (unless you use functions internal to the F# Core library that use mutation under the hood). Therefore the best idea is probably to build up a new list from the old one, prepending the next elements as we go, and inserting foo at the right point. At the end, the new list is reversed to obtain the same order as the old list:
let insertFoo (foo : Foo) bar =
let rec loop acc = function
| [] -> prep (foo :: acc) []
| x :: xs ->
if foo.Compare x
then prep (x :: foo :: acc) xs
else loop (x :: acc) xs
and prep acc = function
| [] -> acc
| x :: xs -> prep (x :: acc) xs
loop [] bar |> List.rev
I guess #knocte was quicker with an equivalent solution…
#AlexAtNet's solution doesn't look bad, but if you still want recursive, you can avoid so much concat calls this way:
let rec insertFooInProperPositionTailRec (foo: Foo)
(headListAcc: list<Foo>)
(bar: list<Foo>)
: list<Foo> =
match bar with
| [] -> List.rev (foo::headListAcc)
| head::tail ->
if (foo.Compare(head)) then
let newAcc = List.rev headListAcc
[ yield! newAcc
yield! foo::bar ]
else
let newAcc = head::headListAcc
insertFooInProperPositionTailRec foo newAcc tail
let rec insertFooInProperPosition (foo: Foo) (bar: list<Foo>): list<Foo> =
insertFooInProperPositionTailRec foo [] bar
Not sure if it's more performant than #AlexAtNet's, mmm...

F# Continuation-based tail recursion on list

I have this quite simple function which takes an int and adds it to the head of the list and is recursively called with i multiplied with itself:
let rec f i = function
| [] -> []
| x::xs -> (x+i)::f (i*i) xs
f 2 [1;2;3]
val it : int list = [3; 6; 19]
Now, I'm attempting to rewrite it using a continuation, but I'm a little stuck. Here's what I've come up with so far:
let fC i l =
let rec loop cont = function
| [] -> []
| x::xs -> cont(x+i)::loop (fun acc -> (acc*acc)) xs
loop id l
fC 2 [1;2;3] //Expected [3;6;19]
val it : int list = [3; 16; 25]
Any hints to what I'm doing wrong?
Looking at this questions and the comments it seems to me that there is some confusion.
Tail recursive does not necessary mean continuation passing style (CPS).
Here's the function in CPS:
let f' i p =
let rec loop i p k =
match p with
| [] -> k []
| x::xs -> loop (i*i) xs (fun a -> k ((x+i)::a))
loop i p id
And of course, it's tail recursive. But you can also write it tail recursive by using an accumulator instead of a continuation:
let f'' i p =
let rec loop i p acc =
match p with
| [] -> acc
| x::xs -> loop (i*i) xs ((x+i)::acc)
loop i p [] |> List.rev
See also the answer to this question to understand better CPS.

First and last element of list OCaml

I am trying to get first and last element of the list in OCaml. I expect that my function will be like
'a list -> 'a * 'a
What I am trying to do is
let lista = [1;2;3;4;6;0];;
let rec first_last myList =
match myList with
[x] -> (List.hd lista,x)
| head::tail ->
first_last tail;;
first_last lista;;
Of course because of I made list as integer then I am doing this syntax like
*int list -> int * 'a
The point is that I dont have idea how to do this function for 'a.
Whats the direction?
The direction is to write two different functions first and last and implement the first_and_last function as:
let first_and_last xs = first xs, last xs
Another possibility with only one function:
let rec first_last = function
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You may prefer it like that:
let rec first_last myList = match myList with
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You can create two separate functions to return first element and last element, and then in your first_and_last function return a tuple (first_element, last_element).
let rec first_element list =
match list with
| [] -> failwith "List is empty"
| first_el::rest_of_list -> first_el
let rec last_element list =
match list with
| [] -> failwith "List is empty"
| [x] -> x
| first_el::rest_of_list -> last_element rest_of_list
You can create a helper function that has a base-case of the empty-list - for which it returns itself, and otherwise checks if the next recursive call will return an empty list. If it does, return the current element (which is by definition the last element in the list), and if it doesn't, return what was returned by the recursive call.
For the regular (non-helper) method, if the list is at least one element long (i.e. hd::tl = hd::[]) then you can just concatenate the list you got from the last function onto the head from ls.
It can be implemented as follow:
let rec last ls =
match ls with
| [] -> []
| hd::tl -> let next = last tl in
if next = [] then [hd]
else next
;;
let first_last ls =
match ls with
| [] -> failwith "Oh no!!!!! Empty list!"
| hd::tl -> hd::last tl
;;
Yet another take on this problem.
let first_last xs =
let rec last_non_empty = function
| [x] -> x
| _ :: xs' -> last_non_empty xs'
| [] -> failwith "first_last: impossible case!"
in
match xs with
| [] -> failwith "first_last"
| x::_ -> (x, last_non_empty xs)
Some properties of this implementation:
(1) it meets the specification 'a list -> 'a * 'a:
utop > #typeof "first_last";;
val first_last : 'a list -> 'a * 'a
(2) it works for singleton lists: first_last [x] = (x,x):
utop> first_last [1];;
- : int * int = (1, 1) utop> first_last ["str"];;
- : bytes * bytes = ("str", "str")
(3) it's tail-recursive (hence it won't cause stack overflow for sufficiently big lists):
utop > first_last (Array.to_list (Array.init 1000000 (fun x -> x+1)));;
- : int * int = (1, 1000000)
(4) it traverses the input list one time only; (5) it avoids creating new lists as it goes down the recursive ladder; (6) it avoids polluting the namespace (with the price of not allowing the reuse of a function like last).
And another rather simple variant, from the first principles (I was trying to illustrate "wishful thinking" in the spirit of the SICP book):
(* Not tail-recursive, might result in stack overflow *)
let rec first_last = function
| [] -> failwith "first_last"
| [x] -> (x,x)
| x :: xs -> (x, snd (first_last xs))
You could write it like this:
let first_last = function
| [] -> assert false
| x :: xs -> (x, List.fold_left (fun _ y -> y) x xs)
Or, if you are using the Base library, you could write in this way:
let first_last xs = (List.hd_exn xs, List.reduce_exn ~f:(fun _ y -> y) xs)
The basic idea is that List.fold_left (fun _ y -> y) x xs will compute the last element of x :: xs. You can prove this by induction on xs: if xs = [] then List.fold_left (fun _ y -> y) x [] = x, which is the last element of x :: []; moreover, if xs = x' :: xs' then List.fold_left (fun _ y -> y) x (x' :: xs') can be rewritten as List.fold_left (fun _ y -> y) x' xs', because List.fold_left f acc (x :: xs) = List.fold_left (f acc x) xs, hence we are finished, because this is the last element of x' :: xs' by our induction hypothesis.

Resources