How can I implement the concatenation operator in Haskell by hand?
This is what I have so far, but I am struggling with the recursion at the end:
data MyList a = Empty | Element a (MyList a)
deriving Show
concatenation:: MyList a -> MyList a -> MyList a
concatenation Empty Empty = Empty
concatenation a Empty = a
concatenation Empty a = a
concatenation x y = ???
Instead of using variables directly, we can enumerate over the constructors. There are thus four cases we need to cover:
concatenation:: MyList a -> MyList a -> MyList a
concatenation Empty Empty = -- ...
concatenation Empty (Element b bs) = -- ...
concatenation (Element a as) Empty = -- ...
concatenation (Element a as) (Element b bs) = -- ...
Now we can aim to solve those cases. Concatenating two Empty lists will return an empty list, so Empty.
concatenation Empty Empty = Empty
In case the first list is Empty, and the latter is not, then we return the second list.
concatenation Empty (Element b bs) = Element b bs
in case the first element is a list, and the latter is not, then we can return the first list:
concatenation (Element a as) Empty = Element a as
finally in case both lists are non-empty, then the resulting list starts with the first element of the first list, followed by the concatenation of the tail of the first list, and the second list:
concatenation (Element a as) (Element b bs) = Element a (concatenation as (Element b bs))
this gives us the following code:
concatenation:: MyList a -> MyList a -> MyList a
concatenation Empty Empty = Empty
concatenation Empty (Element b bs) = Element b bs
concatenation (Element a as) Empty = Element a as
concatenation (Element a as) (Element b bs) = Element a (concatenation as (Element b bs))
We can shorten the implementation with as patterns:
concatenation:: MyList a -> MyList a -> MyList a
concatenation Empty Empty = Empty
concatenation Empty bl#(Element b bs) = bl
concatenation al#(Element a as) Empty = al
concatenation (Element a as) bl#(Element b bs) = Element a (concatenation as bl)
But this is rather verbose, furthermore it performs pattern matching on both lists, which can be expensive: if for example the second list requires expensive computations first, and the first list is long enough (or even infinite), then we will never be interested in the second list anyway.
We thus can look if we can compact the number of clauses. The first two lines can be grouped together, from:
concatenation Empty Empty = Empty
concatenation Empty (Element b bs) = Element b bs
to:
concatenation Empty bl = bl
since regardless of the value of the second list, we return that anyway. It also saves us potentially an evaluation, which can result in more effecient code.
Can we do a similar thing with the last two lines?
concatenation (Element a as) Empty = Element a as
concatenation (Element a as) bl#(Element b bs) = Element a (concatenation as bl)
both have as a result an Element constructor, and a as the first element. Since the concatenation of as and Empty is eventually concatenation as Empty = as, we thus can perform a recursive call in the former case as well, and use:
concatenation (Element a as) bl = Element a (concatenation as bl)
and this results into:
concatenation :: MyList a -> MyList a -> MyList a
concatenation Empty bl = bl
concatenation (Element a as) bl = Element a (concatenation as bl)
we can omit the second parameter here with:
concatenation :: MyList a -> MyList a -> MyList a
concatenation Empty = id
concatenation (Element a as) = Element a . concatenation as
Note that the last reduction is not per se more efficient: this can result in constructing an entire copy of a (potentially large) list into memory, and a lot of computations if the second list turns out to be empty. If on the other hand computing the second list would result in getting stuck in an infinite loop or an expensive computation, and we are not interested in that part, we can potentially save a lot of CPU cycles.
Just use the standard recursion:
concatenation:: MyList a -> MyList a -> MyList a
concatenation Empty l = l
concatenation (Element e l1) l2 = Element e (concatenation l1 l2)
Why does it stop? The second rule with take every element of the first list, one by one, and nest it before the concatenation of Empty and the second list, that is the second list itself (first rule).
concatenation Element 1 (... Element n (Empty)) l2
= Element 1 (concatenation Element 2 (... Element n (Empty))) l2 -- second rule
= ...
= Element 1 (Element 2 (... Element n (concatenation Empty l2))) -- second rule
= Element 1 (Element 2 (... Element n (l2))) -- first rule
Related
Good morning,
I have a problem with coding using ocaml so I had to code a function that take on input list then add to this list an element.
But using this does'nt affect the list1 so how can I do this ?
Thank you.
let rec append list1 element list2 = match list2 with
[]-> list1
| e::l -> if ( element = e ) then e :: list1
else (append list1 element l)
;;
List are immutable in OCaml, you can't change this. You can write a function append that takes a list and returns a new list that appends an element to it.
For example, here is the prepend function that takes a list and an element and returns a new list with the given element prepended to the passed list,
let prepend xs x = x :: xs
The append function is a little bit trickier, since lists in OCaml are singly-linked, so it is easy to prepend but hard to append. To implement the append function you need an intermediate list, let's call it acc for accumulator. You then go through each element of the input list and add it to the accumulator. Since you're prepending, then once the input list is over your accumulator will have all the elements of the input list by in the reversed order, i.e., the first element (aka the head) of the acc list will be the last element of the input list. Now you what is left is to prepend the element that we want to append to the reversed acc list and reverse act. Here is the skeleton code for you
let append xs x =
let rec loop xs acc = match xs with
| ... -> ... in
loop xs []
I'm new to F# and I'm trying to write a method split that splits a list into 2 pieces. It takes a tuple with the first element being the number of elements to split and the second element is the list . For example, split (2, [1;2;3;4;5;6]) should return ([1;2], [3;4;5;6]),
This is what I have so far, but for some reason it is returning the second element of the tuple as the original list without the head. I don't understand this because I thought that x::xs automatically makes x the head element and xs the rest of the list, which would mean that each recursive call is taking the tail of the previous list and chopping off the first term.
let rec split = function
|(n, []) -> ([], [])
|(0, xs) -> ([], xs)
|(n, x::xs) -> let temp = x :: fst (split(n-1, xs))
(temp, xs);;
The problem is on this line:
(temp,xs);;
here in your example, xs will always be [2;3;4;5;6] as long as n>0
You need to get the second element of the list with something like
|(n,x::xs) ->
let a,b = split (n-1,xs)
(x::a,b)
I'm learning f# with no prior functional programming background - starting to make progress but been stuck on this one. Could anybody please help me understand the solution to Problem 9 of the 99 f# problems - they can be found here:[http://fssnip.net/an][1]
Basically I don't understand how the pattern matching works in the provided solution. For a start what is xss? cheers for any help!
Problem 9 : Pack consecutive duplicates of list elements into sublists.
If a list contains repeated elements they should be placed in separate sublists.
Example:
pack ['a'; 'a'; 'a'; 'a'; 'b'; 'c'; 'c'; 'a'; 'a'; 'd'; 'e'; 'e'; 'e'; 'e']
val it : char list list =
[['a'; 'a'; 'a'; 'a']; ['b']; ['c'; 'c']; ['a'; 'a']; ['d']; ['e'; 'e'; 'e'; 'e']]
Sample Solution;
let pack xs =
let collect x = function
| (y::xs)::xss when x = y -> (x::y::xs)::xss
| xss -> [x]::xss
List.foldBack collect xs []
To understand this, it is first important to understand how lists are represented in F#. An F# list is either:
an empty list written as [] or
a value (head) followed by another list (tail) written as head::tail
So if you write, for example, [ 1; 2; 3 ] you are actually constructing a list containing 1, followed by a list containing 2, (etc.) followed by an empty list. The expression is compiled to:
1::(2::(3::[]))
And you can omit the brackets and write just 1::2::3::[].
Pattern matching uses exactly the same syntax, but in the opposite direction. Instead of constructing lists, you are decomposing them. So when you have a pattern x::xs it means that you want to take the first element and assign it to a variable x and the remaining list should be assinged to a variable xs.
The pattern (x::xs)::xss is a bit more tricky, because it works on lists of lists. This means that the head of the list you match on is also a list. You could rewrite the code to the following simpler version:
let pack xs =
let collect x = function
| head::xss -> // Decompose into first element (head) and the rest (tail)
match head with
| y::xs when x = y -> (x::y::xs)::xss
| _ -> [x]::xss
| xss -> [x]::xss
List.foldBack collect xs []
Now you have some duplication in the code, but you can see that collect takes x and another parameter, matches that another parameter against head::xss (to get the head/tail) and then also decomposes the head.
(y::xs)::xss matches a (non-empty) list of lists, y and xs being the head and tail of the first sublist and xss being the tail of the outer list. xss, in the second case, matches the entire list (empty or not).
foldBack (('T -> 'State -> 'State) -> 'T list -> 'State -> 'State) threads an accumulator argument through the list, going from back to front.
collect is the "accumulating" function, which basically reads: if the state (initially an empty list) contains at least one sublist, which is also non-empty, and the current element (x) matches the head of the sublist (y), prepend x to the sublist, otherwise prepend a new sublist to the state (xss) consisting solely of x. Each sublist is a group of equal, adjacent elements.
So this is my question: i wanna make a function that takes a list and and int, it then recursively moves through the list, and if it finds an element in the list equal to the int, then it should return the entire list with the element removed, and a boolean indicating wether something was removed. this is what i got so far:
fun foo ([], n) = ([],false)
| foo ((x::xs), n) = if x = n
then (xs,true)
else ([x] # foo(xs,n),false);
my idea was to make the function cons the needed elements inside the tuple like this:
([x0] # [x1] # [x2] # [xs], true)
so is there any way to make this function? keep in mind that it has to stop once it hits the element equal to n, but still retain the rest of the list, and be able to return a boolean. run time is key.
Your current code is close to correct logically, but as you know it doesn't type-check because of [x] # foo (xs, n). foo returns a tuple, which can't be directly appended. Here's how to fix it:
fun foo ([], n) = ([], false)
| foo (x::xs, n) = if x = n
then (xs, true)
else let val (xs', tf) = foo (xs, n) in (x::xs', tf) end
The let is needed to extract the list from the tuple and find out if n was found in the tail of the list. Then we simply put the tuple back together with x consed back on to the front.
I have to iterate over 2 lists. One starts off as a list of empty sublists and the second one has the max length for each of the sublists that are in the first one.
Example; list1 = [[];[];[];]; list2 = [1;2;3]
I need to fill out the empty sublists in list1 ensuring that the length of the sublists never exceed the corresponding integer in list2. To that end, I wrote the following function, that given an element, elem and 2 two lists list and list, will fill out the sublists.
let mapfn elem list1 list2=
let d = ref 1 in
List.map2 (fun a b -> if ((List.length a) < b) && (!d=1)
then (incr d ; List.append a [elem])
else a )
list1 list2
;;
I can now call this function repeatedly on the elements of a list and get the final answer I need
This function works as expected. But I am little bothered by the need to use the int ref d.
Is there a better way for me to do this.
I always find it worthwhile to split the problem into byte-sized pieces that can be composed together to form a solution. You want to pad or truncate lists to a given length; this is easy to do in two steps, first pad, then truncate:
let all x = let rec xs = x :: xs in xs
let rec take n = function
| [] -> []
| _ when n = 0 -> []
| x :: xs -> x :: take (pred n) xs
all creates an infinite list by repeating a value, while take extracts the prefix sublist of at most the given length. With these two, padding and truncating is very straightforwad:
let pad_trim e n l = take n (l # all e)
(it might be a bit surprising that this actually works in a strict language like OCaml). With that defined, your required function is simply:
let mapfn elem list1 list2 = List.map2 (pad_trim elem) list2 list1
that is, taking the second list as a list of specified lengths, pad each of the lists in the first list to that length with the supplied padding element. For instance, mapfn 42 [[];[];[]] [1;2;3] gives [[42]; [42; 42]; [42; 42; 42]]. If this is not what you need, you can tweak the parts and their assembly to suit your requirements.
Are you looking for something like that?
let fill_list elem lengths =
let rec fill acc = function
| 0 -> acc
| n -> fill (elem :: acc) (n - 1) in
let accumulators = List.map (fun _ -> []) lengths in
List.map2 fill accumulators lengths
(* toplevel test *)
# let test = fill_list 42 [1; 3];;
val test : int list list = [[42]; [42; 42; 42]]
(I couldn't make sense of the first list of empty lists in your question, but I suspect it may be the accumulators for the tail-rec fill function.)