I'm trying to implement merge function in OCaml using Tail recursion but I face awkward results. Could anyone help me out with this. Thanks in advance.
let rec merge_helper l1 l2 accum =
match l1 with
[] -> l2#accum
| hd::tl -> (match l2 with
[] -> l1#accum
|x::xs -> merge_helper tl xs l1#l2#accum);;
let merge l1 l2 = merge_helper l1 l2 [];;
merge [1;2;4] [3;4;5];;
- : int list = [4; 5; 2; 4; 4; 5; 1; 2; 4; 3; 4; 5]
First of all your implementation doesn't run in a constant stack space. The xs # ys operation is not tail-recursive, and will make List.length xs calls (thus using this amount of stack frames). Also, the merge function usually preserves the ordering. So you need to have a comparison function, that will compare elements of the list. It is not absolutely clear, what you're expecting from you merge function, and why you classify your result as weird. For me the result matches with the code. What looks very strange to me is that although you're deconstructing l1 and l2 you're not using the result of the deconstruction and adds the whole lists l1 and l2 to the accumulator.
The approach should be the following, take an element from the first list, add this element to the accumulator, and switch the lists. So the induction step of the algorithm is the following:
let rec loop acc xs ys = match xs with
...
| x::xs -> loop (x::acc) ys xs
But if you want to merge two sorted lists preserving the order, then you need to take the smallest element of the two lists at each step.
let merge cmp xs ys =
let rec loop xs ys zs = match xs,ys with
| [],ss|ss,[] -> List.rev_append zs ss
| x :: txs, y :: tys ->
if cmp x y <= 0
then loop txs ys (x::zs)
else loop xs tys (y::zs) in
loop xs ys []
Here in the induction step, we take the smaller element, and continue with the two lists: the tail of the owner of the smaller element (because it is moved into the accumulator), and the second list is taken fully (because nothing is accumulated from it). Since we're prepending elements, they will be in a reversed order, so we will need to something to reverse the result (a usual trade off for tail-recursion). The base case, allows us to short-circuit our algorithm, when one or another list is shorter, and we don't need any more to compare them one-by-one, and can just append the rest part of the longer list to the accumulator zs. We use List.rev_append to append the leftover tail of the list to our accumulator. This function will prepend the reversed version of the first list to the second.
Related
Background
I'm working through Ullmans Elements of ML programming in my spare-time. End goal is to self-study Andrew Appels Modern Compiler Implementation in ML.
In Elements of ML, Ullman describes the difference list:
There is a trick known to LISP programmers as difference lists, in which one
manipulates lists more efficiently by keeping, as an extra parameter of your
function, a list that represents in some way what you have already accomplished.
The idea comes up in a number of different applications;
Ullman uses reverse as an example of the difference list technique. Here is a slow function that runs in O(n^2).
fun reverse nil = nil
| reverse (x::xs) = reverse(xs) # [x]
And the faster one using a difference list
fun rev1(nil, M) = M
| rev1(x::xs, ys) = rev1(xs, x::ys)
fun reverse L = rev1(L, nil)
My problem
I have this Binary Search Tree (BST) data type.
datatype 'a btree = Empty
| Node of 'a * 'a btree * 'a btree
A naive solution for collecting a list of the elements in pre-order would be
fun preOrder Empty = nil
| preOrder (Node(x, left, right)) = [x] # preOrder left # preOrder right
But Ullman points out that the # operator is slow and suggests in exercise 6.3.5 that I implement preOrder using a difference list.
After some head scratching I came up with this function:
fun preOrder tree = let
fun pre (Empty, L) = L
| pre (Node(x, left, right), L) = let
val L = pre(right, L)
val L = pre(left, L)
in
x::L
end
in
pre (tree, nil)
end
It outputs the elements in pre-order. BUT it evaluates the tree in post-order! And the code is uglier than the naive preOrder one.
> val t = Node(5,
Node(3,
Node(1, Empty, Empty),
Node(4, Empty, Empty)),
Node(9, Empty, Empty))
> preOrder t
val it = [5,3,1,4,9] : int list
Prior Art
I tried searching for references to difference lists in ML programming, and found John Hughes original article describing how to use difference lists for reverse.
I also found Matthew Brecknells difference list blog post with examples in Haskell. He makes a distinction between using an accumulator, like Ullmans reverse example and creating a new type for difference lists. He also presents a tree flattener. But I have a hard time understanding the Haskell code and would appreciate a similar expose but in Standard ML.
abc
Question
How implement a function that actually evaluate the tree in pre-order and collects the elements in pre-order? Do I have to reverse the list after my traversal? Or is there some other trick?
How can I generalize this technique to work for in-order and post-order traversal?
What is the idiomatic way for using a difference list for a BST algorithm?
Your eventual method of doing this is is the best it reasonably gets. The nice way to do this turns out to be
fun preOrderHelper (Empty, lst) = lst
| preOrderHelper (Node(x, left, right), lst) =
x :: preOrderHelper(left, preOrderHelper(right, lst))
fun preOrder tree = preOrderHelper(tree, Nil)
Note that the run time of preOrderHelper(tree, list) is only a function of tree. Call r(t) the run time of preOrderHelper on tree t. Then we have r(Empty) = O(1) and r(Node(x, left, right)) = O(1) + r(left) + r(right), so clearly r(t) is linear in the size of t.
What is the derivation of this technique? Is there a more principled way of deriving it? In general, when you're turning a data structure into a list, you want to foldr onto an empty list. I don't know enough ML to say what the equivalent of typeclasses is, but in Haskell, we would approach the situation as follows:
data Tree a = Empty | Node a (Tree a) (Tree a)
instance Foldable Tree where
foldr f acc t = foldrF t acc where
foldrF Empty acc = acc
foldrF (Node x left right) acc = f x (foldrF left (foldrF right acc))
To convert a Tree a to a [a], we would call Data.Foldable.toList, which is defined in Data.Foldable as
toList :: Foldable f => f a -> [a]
toList = foldr (:) []
Unfolding this definition gives us the equivalent of the ML definition above.
As you can see, your technique is actually a special case of a very principled way to turn data structures into lists.
In fact, in modern Haskell, we can do this totally automatically.
{-# LANGUAGE DeriveFoldable #-}
data Tree a = Empty | Node a (Tree a) (Tree a) deriving Foldable
will give us the equivalent(*) of the above Foldable implementation automatically, and we can then immediately use toList. I don't know what the equivalent is in ML, but I'm sure there's something analogous.
The difference between ML and Haskell is that Haskell is lazy. Haskell's laziness means that the evaluation of preOrder actually walks the tree in the pre-Order order. This is one of the reasons I prefer laziness. Laziness permits very fine-grained control over the order of evaluation without resorting to non-functional techniques.
(*) (up to the arguments order, which does not count in the lazy Haskell.)
What you show is not what I've seen usually referred to as difference list.
That would be, in pseudocode,
-- xs is a prefix of an eventual list xs # ys,
-- a difference between the eventual list and its suffix ys:
dl xs = (ys => xs # ys)
and then
pre Empty = (ys => ys) -- Empty contributes an empty prefix
pre (Node(x, left, right)) = (ys =>
-- [x] # pre left # pre right # ys -- this pre returns lists
(dl [x] . pre left . pre right) ys) -- this pre returns diff-lists
-- Node contributes an [x], then goes
-- prefix from `left`, then from `right`
so that
preOrder tree = pre tree []
where . is the functional composition operator,
(f . g) = (x => f (g x))
Of course since dl [x] = (ys => [x] # ys) = (ys => x::ys) this is equivalent to what you show, in the form of
--pre Empty = (ys => ys) -- Empty's resulting prefix is empty
pre' Empty ys = ys
--pre (Node(x, left, right)) = (ys =>
pre' (Node(x, left, right)) ys =
-- [x] # pre left # pre right # ys
-- (dl [x] . pre left . pre right) ys
x::( pre' left ( pre' right ys))
-- preOrder tree = pre' tree []
Operationally, this will traverse the tree right-to-left in an eager language, and left-to-right in a lazy one.
Conceptually, seen left-to-right, the resulting list has [x] and then the result of traversing left and then the result of traversing right, no matter what was the tree traversal order.
These difference lists are just partially applied # operators, and appending is just functional composition:
dl (xs # ys) == (dl xs . dl ys)
-- or:
dl (xs # ys) zs == (dl xs . dl ys) zs
== dl xs ( dl ys zs)
== xs # (ys # zs)
the prefix xs # ys is the prefix xs, followed by the prefix ys, followed by whatever the eventual suffix zs will be.
Thus appending these difference lists is an O(1) operation, the creation of a new lambda function which is a composition of the arguments:
append dl1 dl2 = (zs => dl1 ( dl2 zs))
= (zs => (dl1 . dl2) zs )
= (dl1 . dl2)
Now we can easily see how to code the in-order or post-order traversals, as
in_ Empty = (ys => ys)
in_ (Node(x, left, right)) = (ys =>
-- in_ left # [x] # in_ right # ys
(in_ left . dl [x] . in_ right) ys)
post Empty = (ys => ys)
post (Node(x, left, right)) = (ys =>
-- post left # post right # [x] # ys
(post left . post right . dl [x]) ys)
Focusing on just lists [x] and their appending # lets us treat this uniformly -- no need to concern ourselves with :: and its arguments which have different types.
The types of both arguments of # are the same, just as they are for + with integers and indeed . with functions. Such types paired with such operations are known as monoids, under the condition that the appending operation is associative, (a+b)+c == a+(b+c), and there is an "empty" element, e # s == s # e == s. This just means that the combination operation is "structural" in some way. This works with apples and oranges, but atomic nuclei -- not so much.
I'm trying to self-learn some programming in a functional programming language and recently stumbled on the problem of generating all the permutations of length m from a list of length n, with repetition. Mathematically, this should result in a total of n^m possible permutations, because each of the m 'slots' can be filled with any of the n elements. The code I have currently, however, does not give me all the elements:
let rec permuts n list =
match n, list with
0, _ -> [[]]
| _, [] -> []
| n, h :: t -> (List.map (fun tt -> h::tt) (permuts (n-1) list))
# permuts n t;;
The algorithm basically takes one element out of a list with m elements, slaps it onto the front of all the combinations with the rest of the elements, and concatenates the results into one list, giving only n C m results.
For example, the output for permuts 2 [1;2;3] yields
[[1;1]; [1;2]; [1;3]; [2;2]; [2;3]; [3;3]]
whereas I actually want
[[1;1]; [1;2]; [1;3]; [2;1]; [2;2]; [2;3]; [3;1]; [3;2]; [3;3]]
-- a total of 9 elements. How do I fix my code so that I get the result I need? Any guidance is appreciated.
Your error appears on the second line of:
| n, h :: t -> List.map (fun tt -> h::tt) (permuts (n-1) list)
# permuts n t
Indeed, with this you are decomposing the set of n-tuples with k elements as the sum of
the set of (n-1)-tuples prefixed with the first element
the set of n-tuples with (k-1) elements
Looking at the cardinal of the three sets, there is an obvious mismatch since
k^n ≠ k^(n-1) + (k-1)^n
And the problem is that the second term doesn't fit.
To avoid this issue, it is probably better to write a couple of helper function.
I would suggest to write the following three helper functions:
val distribute: 'a list -> 'a list -> 'a list list
(** distribute [x_1;...;x_n] y returns [x_1::y;...x_n::y] *)
val distribute_on_all: 'a list -> 'a list list
(** distribute_on_all x [l_1;...;l_n] returns distribute x l_1 # ... # distribute x l_n *)
val repeat: int -> ('a -> 'a) -> 'a -> 'a
(** repeat n f x is f(...(f x)...) with f applied n times *)
then your function will be simply
let power n l = repeat n (distribute_on_all l) [[]]
In Haskell, it's very natural to do this using a list comprehension:
samples :: Int -> [a] -> [[a]]
samples 0 _ = [[]]
samples n xs =
[ p : ps
| p <- xs
, ps <- samples (n - 1) xs
]
It seems to me you never want to recurse on the tail of the list, since all your selections are from the whole list.
The Haskell code of #dfeuer looks right. Note that it never deconstructs the list xs. It just recurses on n.
You should be able to copy the Haskell code using List.map in place of the first two lines of the list comprehension, and a recursive call with (n - 1) in place of the next line.
Here's how I would write it in OCaml:
let perm src =
let rec extend remaining_count tails =
match remaining_count with
| 0 -> tails
| _ ->
(* Put an element 'src_elt' taken from all the possible elements 'src'
in front of each possible tail 'tail' taken from 'tails',
resulting in 'new_tails'. The elements of 'new_tails' are one
item longer than the elements of 'tails'. *)
let new_tails =
List.fold_left (fun new_tails src_elt ->
List.fold_left (fun new_tails tail ->
(src_elt :: tail) :: new_tails
) new_tails tails
) [] src
in
extend (remaining_count - 1) new_tails
in
extend (List.length src) [[]]
The List.fold_left calls may look a bit intimidating but they work well. So it's a good idea to practice using List.fold_left. Similarly, Hashtbl.fold is also common and idiomatic, and you'd use it to collect the keys and values of a hash table.
I'm trying to implement a function used to split a list into two equal-length halves (the problem assumes the list is of even length) in F#. Using the search function yielded a thread that deals with the exact same problem I'm trying to work through now:
Split list into two equal lists in F#
I'm trying to implement the solution given by the user Juliet, who provides a partial answer:
let cut l =
let rec cut = function
| xs, ([] | [_]) -> xs
| [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys)
cut (l, l)
Which returns the second half of the list. I'm trying to work out a way to return the first half, so I made some modifications:
let rec cut(xs, ys) =
let zs = []
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
x::zs
cut (xs, ys)
You can probably tell that F# is my first functional programming language, and I'm kinda confused as to how it works, exactly. Pattern-matching is a new thing for me, and I was never very good at recursion to start with.
From what I understand, the way pattern matching works is that it's basically a more versatile version of an if-then-else statement, where the code to the left of the -> is the conditional (the "if" bit), and everything to the right is the block of code to execute if the conditional check passes (the "then" bit).
What I'm not totally sure of is whether you're allowed to do things like this:
| x::xs, y1::y2::ys ->
x::zs
cut (xs, ys)
If pattern matching really does work like if statements, then it should be, since in an if statement it would look something like
if (x::xs && y1::y2::ys)
{
x::zs
cut (xs, ys)
}
Anyhow, it doesn't seem like the statement x::zs is allowed, since Visual Studio gives me a warning:
The result of this expression is implicitly ignored. Consider using "ignore" to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. let result = expr'.
I'm not sure what it means by that last part. I thought I had already declared the list as a local variable of the function in the line
let zs = []
All I'm trying to do is take the head of the list xs in each recursive iteration of the cut function and add it to another list zs, which when the base case is reached, would contain every element x passed over (in other words, the first half of the list), then return both xs (which contains the second half of the list) and the list containing the first half, but it doesn't seem like that's allowed?
Anyhow, it doesn't seem like the statement x::zs is allowed, since Visual Studio gives me a warning.
The expression x::zs is allowed, but Visual Studio is trying to tell you that it has no effect. x::zs creates a new list but then immediately discards it (it does not mutate the existing value!).
Based on the rest of the code provided, zs should contain the first half of the list, but zs will only ever contain the empty list [] because that's the only value it is assigned to. In a language like C#, you would simply mutate the list by appending to it but in F# you shouldn't do that. Since you're already using recursion, this is a sign that zs should be a parameter to your recursive function so that you can use the new value later. (I've found that some people understand recursion better if they think of it as a callback. When you recurse, it's like providing parameters to a callback function. Any values you want to accumulate during the recursion process need to be provided as parameters to your function.)
Putting this all together, I think what you want is something like this:
let rec cut(xs, ys, zs) =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
cut (xs, ys, x::zs)
Typically, you'd hide this function inside a non-recursive function which sets up your arguments correctly:
let cut(xs, ys) =
let rec impl(xs, ys, zs) =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
impl (xs, ys, x::zs)
impl(xs, ys, [])
Note: There's no need to use ,s to seperate arguments in F#. When you do this, you are actually declaring that a function has a single argument consisting of a tuple. This is not usually what you want and it prevents currying the function. All you need to use to separate arguments is whitespace:
let cut xs ys =
let rec impl xs ys zs =
match xs, ys with
| xs, ([] | [_]) -> (xs, zs)
| [], _ -> ([], [])
| x::xs, y1::y2::ys ->
impl xs ys (x::zs)
impl xs ys []
Here's a way to do it by adding another accumulator value that builds up the slow items into a list:
let cut l =
let rec loop acc rem =
match rem with
| xs, ([] | [_]) -> List.rev acc, xs
| [], _ -> [], []
| x::xs, y::y'::ys -> loop (x::acc) (xs, ys)
loop [] (l, l)
> cut [1;2;3;4;5;6]
([1; 2; 3], [4; 5; 6])
I am a new to SML and I want to write a function splitup : int list -> int list * int list that given a list of integers creates from two lists of integers, one containing the non-negative entries, the other containing the negative entries.
Here is my code :
fun splitup (xs :int list) =
if null xs
then ([],[])
else if hd xs < 0
then hd xs :: #1 splitup( tl xs)
else hd xs :: #2 splitup( tl xs)
Here's the warning i get:
ERROR : operator and operand don't agree
ERROR : types of if branches do not agree
The function splitup(tl xs) should return int list * int list so i think my recursion should be all right.
What is the problem and how can i fix it ?
The problem is that
hd xs :: #1 splitup( tl xs)
and
hd xs :: #2 splitup( tl xs)
are lists – you can tell from the :: – not pairs of lists as the result should be.
For the non-empty case, you need to first split the rest of the list, then attach the head to the correct part of the result and add it the other part of the result in a pair.
It's also a good idea to get used to pattern matching, as it simplifies code lot.
Something like this:
fun splitup [] = ([], [])
| splitup (x::xs) = let (negatives, non_negatives) = splitup xs
in if x < 0
then (x :: negatives, non_negatives)
else (negatives, x :: non_negatives)
end
There is already List.partition: ('a -> bool) -> 'a list -> 'a list * 'a list, a higher-order library function that does this. In case you want to split up integers into (negative, non-negative):
val splitup = List.partition (fn x => x < 0)
I'm trying to write a function which insert an integer n in every position of a given list. Little example, insert_everywhere 0 [1;2] -> [[0;1;2]; [1;0;2]; [1;2;0]]. I wrote this :
let insert_everywhere l n =
let l_aux = [] in
let rec aux l1 l2 = match l1 with
| [] -> []
| x::tl -> (l_aux # [n] # l1) :: aux tl (l_aux # [x])
in aux l l_aux
;;
The probleme is that calling aux tl (l_aux # [x]) doesn't do what I want. My idea is: when I'm reading the head of my list, I insert into an another list which I append to the number n and the rest of the list. With this way, I will have the final list of list that I excepted but not with my current implementation…
Well, solution is strongly related to data structure called zipper. You need to keep not evaluated tail of list if 1st argument of aux and also keep evaluated prefix of list to build a part of answer of it. You don't need l_aux, we will use 2nd argument instead of using mutable variable. Let's look at skeleton
let insert_everywhere l (n : int) =
let rec aux l1 l2 : int list list = match l1 with
| [] -> (* There we need to built a part of answer
from l1 prefix, n and empty tail postfix*)
| x::tl -> (* There we need to construct part of answer *)
:: aux tl ( (* construct new prefix from old one and `n` there *) )
in
aux l []
If you still can't find answer you can look at my solution there. I will add it to my answer when you will find an answer. Try not to peep into link! :)
P.S.
let insert_everywhere l (n : int) =
let rec aux l1 l2 = match l1 with
| [] -> [l2 # [n]]
| x::tl -> (l2 # [n] # l1) :: aux tl (l2 # [x])
in
aux l []