What does this function in OCaml do? - ocaml

What does this function do in OCaml?
let rec pack xs =
match xs with
| [] -> []
| [x] -> [[x]]
| first :: second :: rest ->
if first = second then
let (firstC :: restC) = pack rest in
(first :: firstC) :: restC
else
[first] :: pack rest
I especially am confused with the line:
let (firstC :: restC) = pack rest in
(first :: firstC) :: restC

The let expression in OCaml looks like this:
let <pattern> = <expr1> in <expr2>
In the expression you're asking about, the pattern is firstC :: restC. This is a pattern that matches any non-empty list. The first element of the list is bound to firstC and the rest of the list is bound to restC.
The pattern is matched against expr1, which in your case is pack rest. If pack rest returns a non-empty list, this gives values to firstC and restC.
These bindings are then used in the expr2 of your example, which is:
(first :: firstC) :: restC
This is a list made by adding first to the beginning of the list firstC and then adding this list to the beginning of the list of lists restC.
If pack rest returns an empty list the result will instead be an exception.
Since pack rest can indeed return an empty list, this code looks fairly suspect to me. Here's an example where it fails in this way:
# pack [3; 3];;
Exception: Match_failure ("//toplevel//", 5, 54).
Note that compiler warns you that the pattern firstC :: restC doesn't cover every case. Hence it might produce an exception (which it does).
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
I hope this is helpful.

Related

Accessing specific elements in a list of tuples in f# without libraries

I have a list of tuples with three different elements like so:
[(a0:string, b0:string, c0:int); (a1, b1, c1); (and so on...)].
I need to make a function that takes this list and a "name" in the form of a and gives a list of all the bs where the name matches the a in the tuple. But I'm not sure how to iterate and match everything.
input: function name tuplelist
output: [b0 if a0 = name; b1 if a1 = name; b2 if a2 = name]
I also cannot use libraries!!!
When writing code in a functional style you will often use recursion, if not explicitly then implicitly since most list/array/sequence functions all use recursion under the hood.
In F#, you need to explicitly state that a function is recursive, so the function you create will use the let rec syntax in its definition. Given your requirements, your function will probably look like this:
let rec myFilter (name: string) (input: (string * string * int) list) =
...
For this class of problems, where you iterate over a list recursively, you usually use pattern matching to check if you are at the end of a list, and if so, return an empty list.
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
...
Now you need to write a pattern match that checks the first item in the tuple against the supplied name. You can use pattern matching on the head of the list, and F#'s when syntax to deconstruct the head of the list for comparison
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
| ((a, b, _) :: rest) when a = name -> b :: myFilter name rest
...
This second case matches when a matches the queried name. When it matches, it will return a new list of which b is the head of the list, and then it will take the rest of the list of tuples and call myFilter recursively. This is how you iterate through the list recursively.
We have one more case to check for: If we don't find a match, we want to keep stepping through the list without collecting b. This can be expressed by peeling off the head and recursively calling myFilter, sending only the rest of the tuples.
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
| ((a, b, _) :: rest) when a = name -> b :: myFilter name rest
| (_ :: rest) -> myFilter name rest
Calling myFilter "a" [("a","x",3);("b","y",4);("a","z",5)] then yields ["x"; "z"], as expected.
Powerful F# pattern matching and recursion along with type inference easily compensate for dropping libraries limitation.
You need to build a map function converting one list into another list, this is to be addressed with recursion, the mapping function applied to each element of the list may use pattern matching to disassemble tuple into components and perform the conversion.
Something like the following will do:
let filter name (tupleList:(string*string*int) list) =
let checkElement name = function | (a,b,c) -> if a = name then Some b else None
let rec mapList name inputList outputList =
match inputList with
| [] -> outputList
| h::t -> let filter = checkElement name h
mapList name t (if filter = None then outputList else (outputList # [filter.Value]))
mapList name tupleList []
Here checkElement is the mapping function that takes the name and a tuple (a,b,c) and returns an option value either Some b if a = name, or None if not.
Recursive function mapList on each step operates with the unprocessed part of inputList of tuples and outputList accumulating on each recursion step parts from matched elements only. On each recursion step it checks if the inputList is empty. If yes, then we are done and it's time to return the accumulated result, otherwise we split the head element off inputList and apply the mapping function to it, changing the accumulated list, if this is the case. Then we do the next recursion step on the tail of inputList and the accumulator.
This task requires you to write your own recursive list processing function. I was able to implement it by using two sub-functions.
While the answers by #GeneBelitski and #ChadGilbert are great for learning, they are not tail-recursive, so I'll add my own.
Sub-function aux takes an accumulator and the list to process, and matches against the shape of the list. If it is empty, it returns the result accumulated so far. If it is a 3-tuple with a tail, it compares the first element to name, and if they are equal, continues running itself prepending the second element to the results accumulated, and the tail of the original list, otherwise just the results accumulated so far, and the tail of the original list.
As this way of accumulating results inverts the order of the resulting list, we need to reverse it before returning it; this is what the sub-function rev does, and as you see, the code looks almost identical to aux, prepending elements to the results accumulated so far but without doing any comparing or processing.
let filter_b name lst =
let rec aux acc = function
| [] -> acc
| (a : string, b : string, c : int) :: tl ->
if a = name
then aux (b :: acc) tl
else aux acc tl
let rec rev acc = function
| [] -> acc
| hd :: tl -> rev (hd :: acc) tl
lst
|> aux [] // process list with aux function
|> rev [] // reverse resulting list

How do I use :: when pattern matching in OCaml

let rec (l:int list) f int list =
match l with
| [] -> []
| hd::tl -> 2+tl
I want to know is hd the first element and then tl is the second element because when i do this I keep getting an error, if tl is not the second element how would i access the second element an in depth explanation of hd::tl would be highly appreciated thank you
No tl is not the second element, it is the rest of the list and it has type 'a list. Here hd and tl are just variable names that you choose to bind to the first element of a list, and to the rest of the list (i.e., to a list that contains all elements except the first one). You can choose other names, e.g., fst::rest. Getting the second element, in that case would be as easy as fst::snd::rest (or x::y::rest - again the name doesn't matter).
What you're trying to use is called pattern matching. It is a feature of some languages, that provides a mechanism to easily deconstruct compound data structures. The idea is that if you're deconstructing data structures the same way as you're constructing them, e.g,
let xs = [1;2;3;4]
and here is the deconstructing
let [x1;x2;x3;x4] = xs
In fact, [x;y;...;z] is a syntactic sugar for a more basic syntax x :: y:: ... :: z :: [], so another way to construct the [1;2;3;4] list is to use the following construct: 1::2::3::4::[]. The same works in the opposite direction, e.g.,
let x1::x2::x3::x4::[] = xs
Now we are ready to the next step, what if the structure on the right doesn't match the structure on the left, e.g.,
let [x;y;z] = [1;2]
or
let x::y::z::[] = 1::2::[]
In that case, the matching will fail. In our case in runtime. To prevent this, and to allow programmers to handle all possible configuration of their data structures OCaml provides the match construct in which you specify multiple variants of the value structure, and the first one that matches is chosen, e.g.,
let orcish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
The function above anticipates only lists that have up to three elements (because Orcs can't count beyond three). But we can. For this we will use the following feature -- if the last element of the list pattern is not [] (that is matches only and only with the empty list, and designates the end-of-list), but anything else (i.e., a variable), then this variable will be bound to all elements, e.g.,
let rec elvish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
| x :: y :: z :: leftovers -> 3 + elvish_length leftovers
So now, we anticipate all possible list patterns. However, the function is now overcomplicated (because Elves are complicating). Now, let's finally derive a normal, human readable, length function,
let rec length xs = match xs with
| [] -> 0
| x :: xs -> 1 + length xs
As an exercise, try to prove to yourself that this function anticipates all possible lists.
:: is read cons and is an infix version of List.cons. In a functional language like Ocaml, list is a linked list where i.e.[e1; e2; e3; e4] can be reduced to something like this:
cons(::)
/ \
e1 cons(::)
/ \
e2 cons(::)
/ \
e3 cons(::)
/ \
e4 [ ]
Basically, any list can be reduced to a tree of recursive cons expressions, which makes recursion so useful in Ocaml or similar functional languages. At each level, you can reduce a list to its head and its tail, where tail is the list minus its head and can be reduced further until last :: []. So with the above example, you can recursively reduce the list until you find the last element by pattern-matching:
let find_last li =
match li with
| [] -> None (* no element *)
| [last] -> Some last (* found last *)
| head :: tail -> find_last tail (* keep finding *)
;;
Note that [last] can be replaced with last::[] and head::tail with List.cons head tail. What is important is at any point a list can always be reduced to head :: tail, where head is the first element and tail is the list without head.
Pattern-matching is useful in matching the "shape" or state of the reducing list.

How can I find the index where one list appears as a sublist of another?

I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.

Error in code to flatten a list in Ocaml

Hello All I am trying to flatten a list in Ocaml. I am a newbie so please pardon me if my mistake is dumb
So for example, if input is [[1];[2;3];[4]] I should end up with [1;2;3;4].
The idea I am trying to use is as follows
Iterate through the list from the right (Using fold_right) with accumaltor = []
The pseudo code is as follows
func flatten(list, accumalator)
For each item from right to left in list
If Item is a scalar then n :: accumalator
Else fi Item is a list of form head :: tail then
head :: flatten (tail, accumalator).
I think that theoretically the algorithm is correct, but please let me know if you disagree.
Now to my OCaml code to implement this algorithm
let rec flatten acc x =
match x with
n -> n :: acc
| [x] -> x :: acc
| head :: remainder ->
head :: ( my_flat acc remainder )
and my_flat = List.fold_right flatten
;;
my_flat [] [[1];[2;3];[4]]
The Error I get is the following
Error: This expression has type 'a but an expression was expected of type
'a list
The error occurs on the line that reads head :: ( my_flat acc remainder ) in the last pattern in the match statement
Any help is appreciated.
In OCaml, all the elements of a list must be the same type. Thus the value [1; [2; 3]; 4] is invalid all by itself. It contains two elements that are of type int and one element of type int list. In essence, your statement of the problem to be solved is impossible.
$ ocaml312
Objective Caml version 3.12.0
# [1; [2; 3]; 4];;
Characters 4-10:
[1; [2; 3]; 4];;
^^^^^^
Error: This expression has type 'a list
but an expression was expected of type int
This sounds like a homework problem, so I'll just say that restricting yourself to lists that are valid in OCaml may make it easier to solve.
Edit
OK, the problem can now be solved!
The essence of the reported type error is something like this. You have your accumulated result acc (of type int list in the example). You want to add the list x (also of type int list) to it. You've broken x into head (an int) and remainder (an int list). As you can see, remainder is not a suitable argument for your my_flat function. It wants an int list list, i.e., a list of lists of ints. In fact, your recursive call should almost certainly go to flatten and not to my_flat.
Another problem I see: the arguments of List.fold_right are: a function, a list, and a starting value. In your test call to my_flat, you're supplying the last two in the other order. The empty list [] is your starting value.
I hope this is enough to get you going. Since you're just starting out with OCaml there will probably be another problem or two before it works.
Edit 2
Here are a couple more comments, which might be spoilers if you're still working on your own solution....
A tidier version of your function my_flat is in the OCaml standard library under the name List.flatten. It's interesting to look at the implementation:
let rec flatten = function
[] -> []
| l::r -> l # flatten r
I'd call this a very elegant solution, but unfortunately it's not tail recursive. So it will consume some (linear) amount of stack space, and might even crash for a very long list.
Here's one based on the same idea, using the standard FP accumulator trick to get tail recursive behavior (as noted by Thomas):
let flatten2 ll =
let rec go acc = function
| [] -> List.rev acc
| l :: r -> go (List.rev_append l acc) r
in
go [] ll
As is often the case, the tail recursive version accumulates the result in reverse order, and reverses it at the end.
You can start by writing directly your algorithm, by decomposing the base cases of your input value, ie. the input list is either empty, or the head of the input list is empty, or the head of the input list has a head and a tail:
let rec flatten = function
| [] -> []
| [] :: t -> flatten t
| (x::y) :: t -> x :: (flatten (y::t))
You can then optimize the function, because this code is not tail-recursive and thus will crash when lists become too big. So you can rewrite this by using the usual technique:
let flatten list =
let rec aux accu = function
| [] -> accu
| [] :: t -> aux accu t
| (x::y) :: t -> aux (x::accu) (y::t) in
List.rev (aux [] list)
So my advice is: start by decomposing your problem based on the input types, and then later use accumulators to optimize your code.
I like this one, where the auxiliary function takes the accumulator, the first element of the list of lists, and the rest of the list of lists, it is clearer for me :
let flatten list =
let rec aux acc list1 list2 =
match list1 with
| x :: tail -> aux (x :: acc) tail list2
| [] ->
match list2 with
| [] -> List.rev acc
| x :: tail -> aux acc x tail
in
aux [] [] list
Thanks for all your help
Here is the code I used to solve this problem
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> head :: ( flatten_each acc remainder )
in
List.fold_right flatten_each ( List.rev list ) []
;;
Edit: as pointed out by Thomas this solution is not tail recursive. Tail recursive version is below
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> (flatten_each (acc # [head]) remainder )
in
List.fold_right flatten_each list []
;;

Haskell - how to create a function that returns the fifth element from a list

How to create a function in Haskell that returns the fifth element from a list.
Something like this:
fifth [] = []!!4
Should return this:
*Main> fifth [1,2,3,20,30,40]
30
Simply use:
fifth :: [a] -> a
fifth l = l !! 4
Using fifth [] like you suggest is wrong since that will pattern match the list against the empty list — you simply want to bind a variable name to the full list so that you can use the !! function afterwards.
You can even define the function as:
fifth :: [a] -> a
fifth = (!!4)
Here we use partial application: you normally think of !! as a function taking two arguments: a list and an integer. We can provide it with one of the arguments and get a new function (fifth) that only takes a list. When we provide (!!4) with a list, it returns the fifth element:
Prelude> let fifth = (!!4)
Prelude> fifth [1,2,3,20,30,40]
30
The function is of course a partial function since it will fail for small lists:
Prelude> (!!4) [1,2,3,20]
*** Exception: Prelude.(!!): index too large
That's to be expected. If you want, you can make it safe by letting it return Maybe a instead of a::
fifth :: [a] -> Maybe a
fifth (a:b:c:d:e:rest) = Just e
fifth _ = Nothing
Here the first pattern will match lists of length 5 or more, and the second pattern matches anything not matched by the first. You use it like this:
*Main> fifth [1,2,3,20,30,40]
Just 30
*Main> fifth [1,2,3,20]
Nothing
You have now forced yourself to always pattern match the result of fifth against either Just a or Nothing. This means that when you code calls fifth someList, then it must take into account that someList might be too short. That way you can ensure at compile time that there wont be any runtime errors from this function.
I would define a safe-indexing operator !!! and then define fifth in terms of !!!.
(!!!) :: [a] -> Int -> Maybe a
xs !!! n | n < 0 = Nothing
[] !!! _ = Nothing
(x : _) !!! 0 = Just x
(_ : xs) !!! n = xs !!! (n - 1)
fifth :: [a] -> Maybe a
fifth = (!!! 4)
Another unsafe variant would be
fifth = head . drop 4
But hey, sometimes one just knows this damn list will have more than 4 elements. The type system is just not powerful enough to express it (using standard lists, that is).