How can I match an empty list of tuples? - list

The following function gives a compilation error at the point I try to match an empty list:
let rec tuplesToList (acc: int list) (remaining: int*int list) =
match remaining with
| [] -> acc
| (a, b) :: tail -> tuplesToList (a :: b :: acc)
The error is:
This expression was expected to have type int * int list but here has type 'a list
This works fine when remaining is a simple list of ints rather than tuples. How can I match an empty list of tuples?

[] is just fine to match an empty list of tuples. But according to your type annotation, remaining is not a list of tuples, it's a tuple containing an int and an int list. A list of tuples would be (int*int) list. int * int list is parsed as int * (int list), not (int * int) list.
If you fix the type, your code should work fine.

In addition to sepp2k's observation, you've also forgotten the second parameter (tail) in the recursive call. Also, your code works fine without any type annotations whatsoever:
let rec tuplesToList acc remaining =
match remaining with
| [] -> List.rev acc //reverse to preserve original order
| (a, b) :: tail -> tuplesToList (a :: b :: acc) tail

Related

Int lists in functions

Does this function take two int lists "x and y" and return an int list of y-x?
let rec fun4 (l: int list) :int list =
begin match l with | [] -> []
| [_] -> []
| x::y::rest -> (y-x)::(fun4 (y::rest))
end
A list is defined as a recursive type:
type 'a list =
| [] of 'a list (* the empty case *)
| ( :: ) of 'a * 'a list
So you basically have two constructors: [] which is the empty list, and x :: other_list which is a list with x as head and other_list as tail. The use of these constructors makes it easy to define a list: [0; 1; 2; 3] is exactly the same of 0 :: 1 :: 2 :: 3 and of (::) (0, (::) (1, (::) (2, (::) (3, [])))) (which is not very pleasant to read).
Recursive algebraic types, here we have the conjunction of sums ([] and (::)) and products (('a * 'a list)), combined with pattern matching make it possible to describe all sorts of common data structures, as well as their functions for consuming, modifying etc.
In your example, you use pattern matching to deconstruct the list:
let rec fun4 my_list =
match my_list with
(* if my list is empty, I can't process the function so
I return the empty list *)
| [] -> []
(* if my list my list has only one element, I can't process the function
so, like in the previouse case, I return the empty list *)
| [ _ ] -> []
(* Here is the last case of the function, If I almost have two elements in the
list. Remember that empty list is also a list ! *)
| x :: y :: rest -> (y - x) :: (fun4 (y :: rest))
As you can see, Recursives Algebraic data types coupled with pattern matching are a powerful for describing data structures (like list but also many others) and for writing function that use those data structures.

How to implement OCaml function of type (string*int) list -> (string * int list) list where the output list is a tally of the items in the input

The question I have is how might I transform a list of a string and integer pair to a list of string and int list pairs.
For example, if I have the list [("hello",1) ; ("hi", 1) ; ("hello", 1) ; ("hi", 1) ; ("hey",1 )] then I should get back [("hello",[1;1]) ; ("hi", [1;1]) ; ("hey",[1])] where basically from a previous function I wrote that creates string * int pairs in a list, I want to group every string that's the same into a pair that has a list of ones of a length = to how many times that exact string appeared in a pair from the input list. Sorry if my wording is confusing but I am quite lost on this function. Below is the code I have written so far:
let transform5 (lst: (string *int) list) : (string *int list) list =
match lst with
| (hd,n)::(tl,n) -> let x,[o] = List.fold_left (fun (x,[o]) y -> if y = x then x,[o]#[1] else
(x,[o])::y,[o]) (hd,[o]) tl in (x,[1])::(tl,[1])
Any help is appreciated!
General advice on how to improve understanding of core concepts:
The code suggests you could use more practice with destructuring and manipulating lists. I recommend reading the chapter on Lists and Patterns in Real World Ocaml and spending some time working through the first 20 or so 99 OCaml Problems.
Some pointers on the code you've written so far:
I have reorganized your code into a strictly equivalent function, with some annotations indicating problem areas:
let transform5 : (string * int) list -> (string * int list) list =
fun lst ->
let f (x, [o]) y =
if y = x then (* The two branches of this conditional are values of different types *)
(x, [o] # [1]) (* : ('a * int list) *)
else
(x, [o]) :: (y, [o]) (* : ('a * int list) list *)
in
match lst with
| (hd, n) :: (tl, n) -> (* This will only match a list with two tuples *)
let x, [o] = List.fold_left f (hd, [o]) tl (* [o] can only match a singleton list *)
in (x, [1]) :: (tl, [1]) (* Doesn't use the value of o, so that info is lost*)
(* case analysis in match expressions should be exhaustive, but this omits
matches for, [], [_], and (_ :: _ :: _) *)
If you load your code in utop or compile it in a file, you should get a number of warnings and type errors that help indicate problem areas. You can learn a lot by taking up each of those messages one by one and working out what they are indicating.
Refactoring the problem
A solution to your problem using a fold over the input list is probably the right way to go. But writing solutions that use explicit recursion and break the task down into a number of sub-problems can often help study the problem and make the underlying mechanics very clear.
In general, a function of type 'a -> 'b can be understood as a problem:
Given a x : 'a, construct a y : 'b where ...
Our function has type (string * int) list -> (string * int list) list and you
state the problem quite clearly, but I've edited a bit to fit the format:
Given xs : (string * int) list, construct ys: (string * int list) list
where I want to group every string from xs that's the same into a pair
(string * int list) in ys that has a list of ones of a length = to how
many times that exact string appeared in a pair from xs.
We can break this into two sub-problems:
Given xs : (string * int) list, construct ys : (string * int) list list where each y : (string * int) list in ys is a group of the items in xs with the same string.
let rec group : (string * int) list -> (string * int) list list = function
| [] -> []
| x :: xs ->
let (grouped, rest) = List.partition (fun y -> y = x) xs in
(x :: grouped) :: group rest
Given xs : (string * int) list list, construct ys : (string * int list) list where for each group (string, int) list in xs we have one (s : string, n : int list) in ys where s is the string determining the group and n is a list holding all the 1s in the group.
let rec tally : (string * int) list list -> (string * int list) list = function
| [] -> []
| group :: xs ->
match group with
| [] -> tally xs (* This case shouldn't arise, but we match it to be complete *)
| (s, _) :: _ ->
let ones = List.map (fun (_, one) -> one) group in
(s, ones) :: tally xs
The solution to your initial problem will just be the composition of these two sub-problems:
let transform5 : (string * int) list -> (string * int list) list =
fun xs -> (tally (group xs))
Hopefully this is a helpful illustration of one way to go about decomposing these kinds of problems. However, there are some obvious defects with the code I have written: it is inefficient, in that it creates an intermediate data structure and it must iterate through the first list repeatedly to form its groups, before finally tallying up the results. It also resorts to explicit recursion, whereas it would be preferable to use higher order functions to take care of iterating over the lists for us (as you tried in your example). Trying to fix these defects might be instructive.
Reconsidering our context
Is the problem you've posed in this SO question the best sub-problem from the overall task you are pursuing? Here are two questions have occurred to me:
Why, do you have a (string * int) list where the value of int is always 1 in the first place? Does this actually carry any more information than a string list?
In general, we can represent any n : int by a int list which contains only 1s and has length = n. By why not just use n here?

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

OCaml recursive function int list -> int -> (int list * int list)

Studying for a midterm and was looking through some old exam questions. This one doesn't have a solution posted and is stumping me:
partition: int list -> int -> (int list * int list) divides its
first argument into two lists, one containing all elements less than
its second argument, and the other all the elements greater than or
equal to its second argument. partition [5;2;10;4] 4 = ([2],
[5;10;4])
oh, and i'm supposed to be able to find the solution without using an auxiliary function
here is as far as i've gotten:
let rec partition l n = match l with
| [] -> ([], []) (* must return this type *)
| x :: xs -> if x < n then (* append x to first list, continue recursing *)
else (* append x to second list, continue recursing *)
normally, I'd use an aux function with an extra parameter to store the pair of lists i'm building, but that can't be done here. i'm a bit stuck
You should use the let in construction to match the return value of the recursive call:
let rec partition l n = match l with
| [] -> ([], [])
| x :: xs -> let a, b = partition xs n in
if x < n then (x::a), b
else a, (x::b);;

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 []
;;