OCaml pattern match arbitrarily many list elements - list

Say I have lists like [1;2;3;4;5;6;9] and [1;2;3;9] and I want to write a pattern which captures lists which begin with 1 and end with 9, and also capture the values of the middle of the list. Is this possible to do with OCaml's pattern matching?
I've tried to write something like
match l with
| 1::middle::9
or
match l with
| 1::middle::9::[]
but I'm not sure that these are doing what I want, and are probably instead only matching 3 element lists. Is there an approach I can take to match things like this? Should I be using nested pattern matches?

There's no pattern that matches the end of a list, so there's no pattern like what you want. You can do two matches:
match l with
| 1 :: _ -> (
match List.rev l with
| 9 :: _ -> true
| _ -> false
)
| _ -> false
Finding the end of a list is a linear time operation. If your lists can be long, you might want to use a different data structure.

If you're just making checks on the first and last elements of a list, you may want to use conditional statements instead of pattern matching:
let is_valid l =
let open List in
let hd' = hd l in (* Get the first element of the list *)
let tl' = rev l |> hd in (* Get the last element of the list *)
if hd' = 1 && tl' = 9 then true else false
is_valid [1;2;3;4;5;6;9] (* bool = true *)
However, if you are trying to extract that middle pattern it may be worthwhile to use pattern matching. We can do something similar to what Jeffery suggested because of the reason he pointed out (pattern matching can't match the end of a list):
let is_valid l =
let open List in
match l with
| 1 :: mid -> (* `mid` holds list without the `1` *)
(match rev mid with (* `rev_mid` holds list without the 9 but reversed *)
| 9 :: rev_mid -> Some (rev rev_mid) (* reverse to get correct order *)
| _ -> None)
| _ -> None
is_valid [1;2;3;4;5;6;9] (* int list option = Some [2; 3; 4; 5; 6] *)
Then with this function, you can use it with simple pattern matching to look for the middle of valid lists:
match is_valid l with
| Some middle -> middle (* the middle of the list *)
| None -> [] (* nothing — list was invalid *)

Related

Insert element in list ocaml

I created a function that insert one element in a list.
The insertion will happens when the element i is equal to k.
The list is a list of (int * string) list , like [(1,"hi")...]
The idea is to create a new list where for each iteration hd is append at the beginning.
When i is found then k is inserted and the function stops.
Here the code :
let rec insert k v list_ =
let rec support k v list _
match list_ with
| (i,value) when i = k -> (k,v) :: tl
| hd :: [] -> hd
| hd :: tl -> hd :: support k v tl in
let inserted = support k v list_
let () =
let k = [ (1,"ciao");(2,"Hola");(3,"Salut") ] in
insert 2 "Aufwidersen" k
I think all is fine but the compiler said :
5 | | hd :: [] -> hd
Error: This pattern matches values of type 'a list
but a pattern was expected which matches values of type 'b * 'c`
And I don't understand why, I think all is ok.
The problem is this part:
match list_ with
| (i,value) -> ...
When you write this, Ocaml infers that list_ has to be a tuple, which is a type error because it is actually a list of tuples.
I didn't understand exactly what you want the insert function but the typical pattern is to have two cases, one for the empty list and one for the non-empty list. I personally prefer using if-then-else instead of pattern guards but if you want to use pattern guards that should also work. Either way, you certainly want to cover the case of the empty list.
match list_ with
| [] -> (* ... *)
| (i,value)::tl ->
if i = k then
(* ... *)
else
(* ... *)

match case unused in OCaml

I want to build a list of type (char, 'a list) list where each char is an upper case letter of the alphabet. I'am getting a warning Warning 11: this match case is unused. for the second match case on get_list. I did some prints on the first case and found out len get's there with value 0, so it never uses the second case. What's happening?
let rec get_list abc i len =
match i with
| len -> []
| _ -> ((String.get abc i), [])::get_list abc (i + 1) len
in
let rec print_list l =
match l with
| [] -> ()
| h::t -> print_char(fst h);print_list t
in
let abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" in
let abc_l = get_list abc 0 (String.length abc) in
print_list abc_l;;
The reason it doesn't work
When you write
match i with
| len -> []
| _ -> ["..."]
len is a generic pattern, which hasn't anything to do with the len define above. In a pattern matching you define only how the variable should look like, you describe it's general "structure", the variable names are used to name the differents parts of the pattern matching, and are new variables. For example with lists you can do:
match my_list with
| [x,y,z] -> x+y+z
| x :: r -> x + (List.length r)
| anything_else -> List.length anything_else
When you put '_' it's only a convention to say "I don't mind which value it is, I don't need it". Here is another example with tuples:
match my_tuple with
| (a,b) -> a+b
A solution : conditionnal pattern matching
If you want to put condition in a pattern matching you can use the when keyword :
match i with
| n when n = len -> []
| _ -> ["..."]
Another example that "sort" a tuple:
match my_tuple with
| (a,b) when a>b -> (a,b)
| (a,b) -> (b,a)
Or just use conditions with integers :
if i = len then []
else ["..."]
You can also note that you can do pattern matching within functions :
let f (a,b) = a+b
The len in your pattern is a new variable introduced by the pattern. As a pattern, its meaning is that it will match anything at all. Thus, the next pattern _ will never match.
As #AlexanderRevyakin says, this new variable len is hiding the parameter that's also named len.
It is not the case that the len in your pattern represents the value of the parameter len. OCaml patterns contain only new variables (to which pieces of the matched value are bound) and constants. They don't contain expressions that are evaluated at run time. For that you want to use if/then/else (as #AntonTrunov points out).

Extract Value from list of lists in OCaml

Lets say I have a list containing and int* list of lists How would I be able to extract the value of the int from this type of list? You could pattern match for the head of the list or the tail but how would you extract the int?
You can always just make two pattern matches in a row
match [[1;2]; [3;4]] with
| (firstrow::_) -> (
match firstrow with ->
| (x :: _) -> x
| [] -> 0 )
| _ -> 42
Its also OK to write pattern matches with multiple levels.
match [[1;2]; [3;4]] with
| (x::_)::_ -> x
| ([]::_) -> 0
| _ -> 42
That said, you don't necessarily need to use pattern matching to access the list elements. You can also use List.map or one of the many other list-manipulation functions depending on what you are actually trying to do.
I don't understand which value you want to extract exactly, by let's say that you want to extract all integers in your int list list and don't want to write pattern matchings with multiple levels, you can first use the List.flatten function to obtain an int list and then do what ever you want to do:
let l = List.flatten [[1; 2]; [3; 4]] in (* l = [1; 2; 3; 4] *)
List.iter print_int l (* iter, map or any other function *)
if you think your list of lists as a matrix and you have the line column you want
List.nth col (List.nth ln matrix)
List.nth is nice to use in this case, with the info you got me i think this is what you want

OCaml: remove the first element of a list

I have a list composed by several couples of numbers:
[(1,2);(3,4);(5,6);(7,8)]
I want to remove the the first element (the head) from the list, so the output should be:
[(3,4);(5,6);(7,8)]
Someone can help me? I was thinking about this function but it doesn't work:
let cut x = function
[] -> []
| (a,b) -> []
| (a,b)::ris -> ris
Just remember, that
let f x y = function -> <code>
is really a shortcut (or a syntactic sugar), for:
let f x y z = match z with -> <code>
So, it just cuts the last argument in a function, and automatically matches on it.
Also, when you pattern matching keep in mind, that all expressions in the left side of pattern match should have the same type. Otherwise, compiler may pick a random one, and decide, that all others have the same type, yielding a somewhat confusing error message. The same is true for the right sides of patter match. So, when you see a compiler message, saying that something is not what he has expected, just check this preconditions:
| [] (* is a list, by definition *)
| (a,b) -> [] (* is a pair, by definition of a pair *)
| (a,b)::ris -> ris (* is a list, by definition of (::) *)
If left part works, look at the right.
Also, if you have a variable that you do not need to use, then you should better give it a name starting with underscore, or just an underscore.
let cut = function
| [] -> []
| _::xs -> xs
You are almost there:
let tl x = match x with
| [] -> [] (* or failwith "empty" *)
| ab::ris -> ris
Few points:
function takes another argument. Your function already get one arg, so use match x with instead.
You are interested only in the list is empty or has a "tail", so you need not pattern-match its element as a tuple.
This function is called "tail", in OCaml, known as List.tl.
You could write simple:
let cut = List.tl
You have little mistake.
Third line should look like
| [(a,b)] -> []
or
| (a,b) :: [] -> []
P.S. by the way, this third line is unnecessary. Just remove it.
And delete x in first line:
let cut = function

How to check in the next 'head' in OCaml is empty?

I'm new at OCaml (and still a novice in learning programming in general) and I have a quick question about checking what kind of string the next element in the string list is.
I want it to put a separator between each element of the string (except for the last one), but I can't figure out how to make the program 'know' that the last element is the last element.
Here is my code as it is now:
let rec join (separator: string) (l : string list) : string =
begin match l with
| []->""
| head::head2::list-> if head2=[] then head^(join separator list) else head^separator^(join separator list)
end
let test () : bool =
(join "," ["a";"b";"c"]) = "a,b,c"
;; run_test "test_join1" test
Thanks in advance!
You're almost there. The idea is breaking down the list in three cases where it has 0, 1 or at least 2 elements. When the list has more than one element, you're safe to insert separator into the output string:
let rec join (separator: string) (l : string list) : string =
begin match l with
| [] -> ""
| head::[] -> head
| head::list-> head^separator^(join separator list)
end
I have several comments about your function:
Type annotation is redundant. Because (^) is string concatenation operator, the type checker can infer types of separator, l and the output of the function easily.
No need to use begin/and pair. Since you have only one level of pattern matching, there is no confusion to the compiler.
You could use function to eliminate match l with part.
Therefore, your code could be shortened as:
let rec join sep l =
match l with
| [] -> ""
| x::[] -> x
| x::xs -> x ^ sep ^ join sep xs
or even more concise:
let rec join sep = function
| [] -> ""
| x::[] -> x
| x::xs -> x ^ sep ^ join sep xs
The empty list is [], the list with one element is [h] and the list with at least one element is h::t. So your function can be written as:
let rec join separator = function
| [] -> ""
| [h] -> h
| h::t -> h ^ separator ^ join separator t