Why am I getting an error in first case but not in second? - functional-programming

I started learning OCaml recently and came across the following problem:
*Write a function last : 'a list -> 'a option that returns the last element of a list. *
I tried the following code:
# let rec last = function
| [] -> None
| _ :: t -> last t
| [x] -> Some x;;
I got the following response:
Characters 65-68:
Warning 11: this match case is unused.
val last : 'a list -> 'a option = <fun>
But the following code compiles without an error:
# let rec last = function
| [] -> None
| [x] -> Some x
| _ :: t -> last t;;
giving the response
val last : 'a list -> 'a option = <fun>
So, my doubt is why just by changing the order I am getting the error?
Any remarks and guidance will be highly appreciated.
I asked this question on programmers.stackexchange As per suggestion I am asking on overflow.

in this line,
| _ :: t -> last t
what is t? it's a list!. That means it could either be a cons cell of (a :: a list), or it could be []. Since this case, along with the first, now match every possible list, the third case cannot be reached.

Related

Apply anonymous functions to trees OCaml

I have an anonymous function but I don't understand how it is applied.
This function works on trees, it creates a list of tuples within nodes and the sum of all the previous nodes (node, sum_nodes).
This is the code :
let rec cost_leaf = function
Empty -> []
| Tr(x,Empty,Empty) -> [(x,x)]
| Tr(x,left,right) -> List.map (function (y,c) -> (y,x+c))
((cost_leaf left) # (cost_leaf right))
I got this : "This function is applied to a tree, defined as :
type 'a tree = Empty | Tr of 'a * 'a tree * 'a tree "
All ok.
"If empty then void list", just to check the return ok.
"If nodes below are empty return (x,x)", because I have to sum these values, ok.
"Apply this function to..." I don't understand what happens next.
List.map applies (function (y,c) -> (y,x+c)) to all the elements of what? I imagine to the list that we will create in the next step but how? When I saw this I thought it was applied to the tree (because we have only this as input) but we can't apply List.map to a tree! (Also because the definition is clear : int tree -> (int * int) list *)).
Can someone explain me how this can works?

Tree to ordered list with tail recursion

I am actually sitting over a hour on a problem and donĀ“t find a solution for it.
I have this data type:
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
And i have to find a function which converts a given tree in a ordered list. There is also no invariant like that the left child has to be less then the right. I already found a "normal" recursion solution but not a tail recursive solution. I already thought about to build a unordered list and sort it with List.sort, but this uses a merge sort which is not tail recursive. Maybe someone has a good advice.
Thank you!
If you want to traverse the tree in order and return a list, that means our function inorder must have the type 'a tree -> 'a list.
let rec inorder t =
match t with
| Empty -> []
| Node (v, l, r) -> List.append (inorder l) (v :: (inorder r)) (* ! *)
However List.append is in tail position, not inorder. Another problem is we have two calls to inorder. If we put inorder l in tail position, inorder r could not possibly be in tail position - and vice versa.
A neat way to work around this problem is continuation passing style. We take our function above and convert it into a helper function with an extra parameter for our continuation, return
(* convert to helper function, add an extra parameter *)
let rec loop t return =
match t with
| Empty -> ...
| Node (v, l, r) -> ...
The continuation represents "what to do next", so instead of sending values directly out of our function, we must hand them to the continuation instead. That means for the Empty case, we'll return [] - instead of simply []
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) -> ...
For the Node (v, l, r) case, now that we have an extra parameter we can write our own continuation that informs loop what to do next. So to construct our sorted list, we will need to loop l, then loop r (or vice versa), then we can append them. We'll write our program just like this.
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop l ... (* build the left_result *)
loop r ... (* build the right_result *)
return (List.append left_result (v :: right_result))
In this next step, we'll fill in the actual lambda syntax for the continuations.
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop l (fun left ->
loop r (fun right ->
return (List.append left (v :: right))))
Last, we define inorder which is a call to loop with the default continuation, identity.
let identity x =
x
let inorder t =
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop r (fun right ->
loop l (fun left ->
return (List.append left (v :: right))))
in
loop t identity
As you can see loop r (fun right -> ...) is in tail position for the Node branch. loop l (fun left -> ...) is in tail position of the first continuation. And List.append ... is in tail position of the second continuation. Provided List.append is a tail-recursive procedure, inorder will not grow the stack.
Note using List.append could be a costly choice for big trees. Our function calls it once per Node. Can you think of a way to avoid it? This exercise is left for the reader.

Using Map.update in OCaml

I am attempting to change the value of a key in a map I made in OCaml:
module TestMap = Map.Make(String);;
let m = TestMap.empty;;
let m = TestMap.add "Chris" 1 m ;;
let m = TestMap.add "Julie" 4 m;;
This compiles file, but when I try to update the value at key Julie with:
let m = TestMap.update "Julie" 10 m;;
I get an error from the compiler:
Error: This expression has type int but an expression was expected of type
'a option -> 'a option
I'm guessing that I'm maybe using the function incorrectly. I'm finding the documentation for Map.update pretty hard to understand:
val update : key -> ('a option -> 'a option) -> 'a t -> 'a t
Is my syntax or are my arguments incorrect?
The update function works in a way different from what you think
key -> ('a option -> 'a option) -> 'a t -> 'a t
You see that second argument is a function which takes an 'a option and returns an 'a option so you don't directly update with a new value but rather pass a function which returns the new value, according to the previous one, eg:
let m = TestMap.update "Julie" (fun _ -> Some 10) m;;
This because, as documentation states, the passed 'a option tells you if there was a mapping for the key and the returned 'a option allows you to change it or even remove it (through None).
If you need just to update a mapping you can use Map.add again, there's no need to use more advanced Map.update.

expression has type 'a list -> 'b list but an expression was expected of type 'b list

This is my function
let rec helper inputList = function
| [] -> []
| a :: b :: hd ->
if a = b then helper ([b::hd])
else a :: helper (b::hd)
It's not complete, however I can't see why I keep getting the error in the title at helper ([b::hd]). I've tried helper (b::hd) or helper (b::hd::[]) however all come up with errors. How do I make it so that it works?
When you use function you are supplying a pattern for the parameter of the function. But you already have a parameter named inputList. So this function helper is expecting two parameters (but it ignores the first).
You can fix this by removing inputList.
You also have a problem in your first recursive call to helper. Your expression [b :: hd] is a list of lists. I suspect that you want something more like just b :: hd here.
There is at least one other problem, but I hope this helps get you started.
There are multiple errors here. One is that the keyword function means we have an implicit parameter over which we are working. So the pattern matching happens on that "invisible" parameter. But here you defined probably the explicit one: inputList. So we can remove that one:
let rec helper = function
| [] -> []
| a :: b :: hd -> if a = b then helper ([b::hd]) else a :: helper (b:: hd)
Next there is a problem with the types: in the recursion, you use:
helper ([b::hd]); and
a :: helper (b:: hd)
But you put these on the same line, and that makes no sense, since the first one passes a list of lists of elements, and the second a list of elements. So the result of the first one would be a list of list of elements, and the second one a list of elements. It does not make sense to merge these.
If I understood correctly that you want to ensure that no two consecutive elements should occur that are equal, then we should rewrite it to:
let rec helper = function
| [] -> []
| a :: b :: hd -> if a = b then helper (b::hd) else a :: helper (b:: hd)
You have defined two patterns here:
one for the empty list; and
one for a list with at least two elements.
The second one will perform recursion on the tail of the list b :: hd. So that means that eventually when we pass it a list with n elements, it will recursively work on a list with n-1 elements, n-2 elements, etc. But eventually it will have one element. And there is no case for that. So we need to add a case for the one element pattern:
let rec helper = function
| [] -> []
| h :: [] -> h :: []
| a :: b :: hd -> if a = b then helper (b::hd) else a :: helper (b:: hd)

Why doesn't my F# map implementation compile

I've started learning F# and I'd like to write my own map function using tail-recursion. Here is what I have
let my_map ff list =
let rec mapAcc ff_inner list_inner acc =
match list_inner with
| [] -> acc
| front::rest -> mapAcc( ff_inner rest (ff_inner(front) :: acc) ) //error
mapAcc ff list []
It would be called like this:
let list = my_map (fun x -> x * 2) [1;2;3;4;5] // expect [2;4;6;8;10]
I get an compilation error message on the second condition that says Type mismatch. Expecting a 'a but given a 'b list -> 'a -> 'a The resulting type would be infinite when unifying ''a' and ''b list -> 'a -> 'a'
I don't know what this error message means. I'm not sure how this can be infinite if I am passing the rest in the recursive call to mapAcc.
Note: I realize I'm rebuilding the list backwards. I'm ignoring that for now.
Just remove the parenthesis when the function calls itself:
let my_map ff list =
let rec mapAcc ff_inner list_inner acc =
match list_inner with
| [] -> acc
| front::rest -> mapAcc ff_inner rest (ff_inner(front) :: acc)
mapAcc ff list []
otherwise everything contained there is interpreted as a single parameter and ff_inner as a function call with the rest as parameters.

Resources