I’m currently learning OCaml, and it’s giving me some problems. I’m trying to implement a merge_sort function, but it keeps giving me an error on the 5th line of the given code. I’m just utterly confused as to why its giving me the error, if anyone could enlighten me, I’d greatly appreciate it. I’m not even really sure if I’m setting up the pattern matching (match statements) correctly, so if you could take look, that’d be really helpful.
let rec merge_sorted (l1:int list) (l2:int list) : int list =
let end_list = [] in
begin match l1, l2 with
| [], [] -> end_list
| h1::t1, h2::t2 -> if h1 < h2 then merge_sorted t1 t2 (h1 :: end_list) else merge_sorted t1 t2 h2::end_list, h1::end_list
end
The error I’m getting is:
Error: This function is applied to too many arguments,
maybe you forgot a `;’
merge_sorted: int list -> int list -> int list
On the part where it says “if h1 < h2 then merge_sorted t1 t2…”
I was also wondering if there are any places to learn OCaml syntax? I’ve been trying to use Jason Hickey’s book, but there are things that it doesn’t go very in depth in (such as this multiple/parallel pattern matching). I’ve only mainly coded in Java, so coding in OCaml has been a bit of a frustrating new experience for me.
You’ve declared
merge_sortedas a function of typeint list -> int list -> int list, or a function that takes two int lists as parameters and returns another int list.The problem you’re encountering is because you’re invoking
merge_sortedwith threeint listarguments:specifically, merge_sorted t1 t2 (h1 :: end_list). You’ve made no provision for the result list in your function definition.
You’ll want to modify your function definition, maybe like so:
Regarding your second question, a decent set of tutorials can be found here.
EDIT
In response to your comment-
First, the
::operator serves two purposes. One, it creates a new list with a new head and an existing tail –1 :: [2]yields[1; 2]. Second, it decomposes existing lists during pattern matches –match [1; 2] with x :: xswill bindxto1andyto[2].That point being addressed, there are a few things in your approach that work fine in Java but will not work at all in OCaml. First, you’re re-declaring
end_listas an empty list in each recursive invocation of your function.Second, because you have your list concatenation on the same line as your recursive call to
merge_sorted, the compiler will (has no choice but to) think that you’re specifying a third function call. What you probably meant is:BUT! This isn’t your solution, read on.
Third and far more importantly, OCaml don’t work this way. By default, OCaml lists (and all variables, actually) are immutable – that is, once you’ve bound a value to one, you can’t change it. When you say (h1 :: end_list), you’re not changing end-list; what you’re actually doing is creating a new list that has h1 as its head and end_list as its tail. Because you have this all on the same line, the compiler thinks that you’re doing the equivalent of
merge_sorted(t1, t2, new List(h1, end_list))in Java-land where you’ve definedmerge_sorted(List t1, List t2).Because you can’t modify your list in-place, functional languages of this stripe have different idioms for list processing. In this case, most functional programmers would have defined their function to take an additional accumulator argument. For example:
This is the canonical
mapfunction, which takes a list and a function, applies each item in the list to that function, and returns a new list containing the results. As you can see, the results of applying each item indatatofare stored inaccand the result is passed to the next call, only to be returned whendatais empty. In this way we can achieve a series of list modifications without needing to mutate a variable.If you don’t like the extra argument in your function signature, you can hide it inside of a nested function like so:
I hope this makes some sense to you – transitioning from imperative to functional idioms can be truly mind-bending, and immutability can seem a cruel and arbitrary limitation to those new to it – I promise that the benefits and the beauty of functional programming will manifest themselves to you if you stick with it!