Sorting in functional programming languages - sorting

I've been learning functional programming for some time, but I haven't read somewhere about sorting with the functional programming languages.
I know the sorting algorithms that are based on value exchanges are hard to implement with the functional idea, but I want to know that are there any sorting algorithms for use in functional programming? What are they?
Thank you.

In a functional language you write a function that given a list returns a sorted list, not touching (of course) the input.
Consider for example merge sorting... first you write a function that given two already sorted lists returns a single sorted list with the elements of both in it. For example:
def merge(a, b):
if len(a) == 0:
return b
elif len(b) == 0:
return a
elif a[0] < b[0]:
return [a[0]] + merge(a[1:], b)
else:
return [b[0]] + merge(a, b[1:])
then you can write a function that sorts a list by merging the resulting of sorting first and second half of the list.
def mergesort(x):
if len(x) < 2:
return x
else:
h = len(x) // 2
return merge(mergesort(x[:h]), mergesort(x[h:]))
About Python syntax:
L[0] is the first element of list L
L[1:] is the list of all remaining elements
More generally L[:n] is the list of up to the n-th element, L[n:] the rest
A + B if A and B are both lists is the list obtained by concatenation
[x] is a list containing just the single element x
PS: Note that python code above is just to show the concept... in Python this is NOT a reasonable approach. I used Python because I think it's the easiest to read if you know any other common imperative language.

Here are some links to sorting algorithms implemented in Haskell:
Quicksort
Insertion sort
Merge sort
Selection sort
Counting sort
Merge sort is often the best choice for sorting linked lists. Functional languages usually operates on lists although I have little knowledge on how most functional languages implements lists. In Common Lisp they are implemented as linked lists and I presume most functional languages do as well.
While quicksort can be written for linked lists it will suffer from poor pivot selection because of random access. While this does not matter on completely random input, on partially or completely sorted input pivot selection becomes very important. Other sorting algorithms may also suffer from the slow random-access performance of linked lists.
Merge sort on the other hand works well with linked lists and it is possible to implement the algorithm such that it only requires some constant of extra space with linked lists.

Here's the classic (pseudo-?)quicksort in Haskell:
sort [] = []
sort (p:xs) = sort [x | x<- xs, x <= p]
++ [p]
++ sort [x | x <- xs, x > p]
See, e.g., c2.com or LiteratePrograms.org. Merge sort isn't much harder to write and more reliable in practice. The same can be done in Scheme with:
(define (sort xs)
(if (null? xs)
'()
(let* ((p (car xs)) (xs (cdr xs)))
(call-with-values (lambda () (partition (lambda (x) (<= x p)) xs))
(lambda (l r)
(append (sort l) (list p) (sort r)))))))
with partition from SRFI-1 (untested code). See also chapter 4 of R6RS libraries.

You certainly can implement imperative, side-effecting sort algorithms in functional languages.
I've implemented a sorting algorithm that operates in-place in a functional programming language called ATS; all mutation is handled by linear types. If you're interested in this kind of thing, drop me a line.

I'm probably raising this question from the grave but I think a global comparison approach might be useful to some people (in case we're not sorting numbers for example). Here is a TypeScript version using ES6:
TL;DR
type Comparator<T> = (itemA: T, itemB: T) => number;
const mergeSort = <T>(list: T[], compare: Comparator<T>): T[] => {
if (list.length <= 1) return list;
const middleIndex = Math.floor(list.length / 2);
const listA = mergeSort(list.slice(0, middleIndex), compare);
const listB = mergeSort(list.slice(middleIndex), compare);
return merge(listA, listB, compare);
};
const merge = <T>(listA: T[], listB: T[], compare: Comparator<T>): T[] => {
if (listA.length === 0) return listB;
if (listB.length === 0) return listA;
return compare(listA[0], listB[0]) <= 0
? [listA[0], ...merge(listA.slice(1), listB, compare)]
: [listB[0], ...merge(listA, listB.slice(1), compare)];
};
Explaination
We can pass an extra compare function to the mergeSort function now. This compare function has the same definition as in JavaScript's Array.prototype.sort() method's parameter.
For instance, the number comparator would be:
const compareNumbers: Comparator<number> = (numberA, numberB) =>
numberA - numberB;
...while a User object comparator could be:
const compareUsersByAge: Comparator<User> = (userA, userB) =>
userA.age - userB.age;
...or anything more complicated if need be (e.g. string comparison).

Related

SML Syntax Breakdown

I am trying to study SML (for full transparency this is in preparation for an exam (exam has not started)) and one area that I have been struggling with is higher level functions such as map and foldl/r. I understand that they are used in situations where you would use a for loop in oop languages (I think). What I am struggling with though is what each part in a fold or map function is doing. Here are some examples that if someone could break them down I would be very appreciative
fun cubiclist L = map (fn x=> x*x*x) L;
fun min (x::xs) = foldr (fn (a,b) => if (a < b) then a else b) x xs;
So if I could break down the parts I see and high light the parts I'm struggling with I believe that would be helpful.
Obviously right off the bat you have the name of the functions and the parameters that are being passed in but one question I have on that part is why are we just passing in a variable to cubiclist but for min we pass in (x::xs)? Is it because the map function is automatically applying the function to each part in the map? Also along with that will the fold functions typically take the x::xs parameters while map will just take a variable?
Then we have the higher order function along with the anonymous functions with the logic/operations that we want to apply to each element in the list. But the parameters being passed in for the foldr anonymous function I'm not quite sure about. I understand we are trying to capture the lowest element in the list and the then a else b is returning either a or b to be compared with the other elements in the list. I'm pretty sure that they are rutnred and treated as a in future comparisons but where do we get the following b's from? Where do we say b is the next element in the list?
Then the part that I really don't understand and have no clue is the L; and x xs; at the end of the respective functions. Why are they there? What are they doing? what is their purpose? is it just syntax or is there actually a purpose for them being there, not saying that syntax isn't a purpose or a valid reason, but does they actually do something? Are those variables that can be changed out with something else that would provide a different answer?
Any help/explanation is much appreciated.
In addition to what #molbdnilo has already stated, it can be helpful to a newcomer to functional programming to think about what we're actually doing when we crate a loop: we're specifying a piece of code to run repeatedly. We need an initial state, a condition for the loop to terminate, and an update between each iteration.
Let's look at simple implementation of map.
fun map f [] = []
| map f (x :: xs) = f x :: map f xs
The initial state of the contents of the list.
The termination condition is the list is empty.
The update is that we tack f x onto the front of the result of mapping f to the rest of the list.
The usefulness of map is that we abstract away f. It can be anything, and we don't have to worry about writing the loop boilerplate.
Fold functions are both more complex and more instructive when comparing to loops in procedural languages.
A simple implementation of fold.
fun foldl f init [] = init
| foldl f init (x :: xs) = foldl f (f init x) xs
We explicitly provide an initial value, and a list to operate on.
The termination condition is the list being empty. If it is, we return the initial value provided.
The update is to call the function again. This time the initial value is updated, and the list is the tail of the original.
Consider summing a list of integers.
foldl op+ 0 [1,2,3,4]
foldl op+ 1 [2,3,4]
foldl op+ 3 [3,4]
foldl op+ 6 [4]
foldl op+ 10 []
10
Folds are important to understand because so many fundamental functions can be implemented in terms of foldl or foldr. Think of folding as a means of reducing (many programming languages refer to these functions as "reduce") a list to another value of some type.
map takes a function and a list and produces a new list.
In map (fn x=> x*x*x) L, the function is fn x=> x*x*x, and L is the list.
This list is the same list as cubiclist's parameter.
foldr takes a function, an initial value, and a list and produces some kind of value.
In foldr (fn (a,b) => if (a < b) then a else b) x xs, the function is fn (a,b) => if (a < b) then a else b, the initial value is x, and the list is xs.
x and xs are given to the function by pattern-matching; x is the argument's head and xs is its tail.
(It follows from this that min will fail if it is given an empty list.)

How to write a loop over a given list in ATS?

Suppose I have a list xs. How do I write the following style of loop in ATS:
foreach x in xs do process(x)
You can use the old DIY-style (also: the classical ATS style), that is to say, using a tail-recursive function. Here's an example:
extern
fun
process (x: int): void
fun
loop {n:int} (xs: list(int, n)): void =
case+ xs of
| list_nil () => ()
| list_cons (x, xs1) => let
val () = process (x)
in
loop (xs1)
end
// end of [loop]
You can run the full code online
I think that this approach is preferable if none of the combinators or template functions provided in the libraries such as ATSLIB is suitable for your case.
A combinator-based solution (for a list0-value):
(xs).foreach()(lam x => process(x))
In ATS, foreach is overloaded with many functions that do some form of sequence traversal.
There is also iforeach if the position of each element is needed:
(xs).iforeach()(lam (i, x) => process(i, x))
This is a POOR solution one needs to avoid!
A beginner of functional programming often does list traversal using the list_get_at function (which overloads the symbol []). For instance, it is fairly common to see code that does more or less what the following line does:
(length(xs)).foreach()(lam i => process(xs[i])) // O(n^2)-time
This is EXTREMELY inefficient. Calling list_get_at inside a loop is almost always a bad idea!

Collection of variable-length Tuples AND map with multiple values TO weighted combinations

This problem is from "Functional Programming Principles in Scala" # Coursera so I need to avoid having complete code in this question - it's past deadline already but there are always years to come. I was looking for general suggestions on methods to implement this transformation.
I have a set of variable-length Tuples, full subset of some String in lowercase
val indexes = Set('a', 'b', 'c')
and a set of tuples with max allowed occurence for each char
val occurences = Set(('a', 1), ('b', 5), ('c', 2))
I want to get combinations of weighted tuples:
val result = Seq(Set(), Set((a, 1)), Set((b, 1)), Set((b, 2)) ... Set((a, 1)(b, 2)(c, 2)) ...)
My assignment suggests easy way of building result via recursive iteration.
I'd like to do it in more "structural?" way. My idea was to get all possible char subsets and multiplex those with added weights (~pseudocode in last line of post).
I got subsets via handly subsets operator
val subsets = Seq(Set(), Set(a), Set(b), Set(c), Set(a, b), Set(a, c), Set(b, c), Set(a, b, c)
and also map of specific Int values for each char, either of
val weightsMax Map(a -> 1, b -> 5, c -> 2)
val weightsAll Map(a -> List(1), b -> List(5,4,3,2,1), c -> List(2,1))
I don't really know which language feature I should use for this operation.
I know about for and collection operations but don't have experience to operate with those on this level as I'm new to functional paradigm (and collection operations too).
I would have no problems with making some corporate-styled java / XML to solve this (yeah ...).
I'd like to have something similar defined:
FOREACH subset (MAP chars TO (COMBINATIONS OF weights FOR chars))
You can express this problem recursively and implement it this exact way. We want to build a function called expend: Set[Char] => List[Set[(Char, Int)]] that returns all the possible combinations of weights for a set of chars (you wrote it chars TO (COMBINATIONS OF weights FOR chars)). The intuitive "by the definition" way is to assign each possible weights to the first char, and for each of these assign each possible weights to the second char and so on...
def expend(set: Set[Char]): List[Set[(Char, Int)]] =
if(set isEmpty) Nil else
allPairsFromChar(set head) flatMap (x => expend(set tail) map (_ + x))
Where allPairsFromChar is trivial from your weightsAll and your FOREACH subset (...) is another flatMap ;)

is this implementation of merge sort good?

I've just started to learn Haskell last night and I've never used a functional programming language before.
I just want to know if my implemention of merge sort is good or bad and what exactly is good or bad.
Maybe it's even wrong - Well it does sort but maybe the Algorithm is not what I think what merge sort is.
Just tell me everything I could improve here. I by myself think its a pretty clear and simple implementation.
Thanks for your advice, here's the code :)
merge [] ys = ys
merge xs [] = xs
merge xs ys = sorted : merge left right
where
sorted = if head(xs) < head(ys) then head(xs) else head(ys)
left = if head(xs) <= head(ys) then tail(xs) else xs
right = if head(xs) > head(ys) then tail(ys) else ys
msort [] = []
msort [x] = [x]
msort xs = merge (msort left) (msort right)
where
left = take (div (length xs) 2) xs
right = drop (div (length xs) 2) xs
Well, first of all, we can rewrite merge to be a little more elegant using pattern matching
merge [] ys = ys
merge xs [] = xs
merge xs#(x:xs1) ys#(y:ys1)
| x <= y = x : merge xs1 ys
| otherwise = y : merge xs ys1
In general you should avoid using head and tail since they are a bit unsafe (they raise an error for the empty list) and use pattern matching whenever possible.
The implementation of msort is pretty much spot on, except that we can split the list in a more efficient way. That's because length xs - takes O(N) to complete. The compiler might save you and cache the result of the length call so that the second call to length won't traverse the list again. But the take and drop will pretty much cause another two traversals thus splitting the list using 3 traversals which may prove to be expensive. We can do better by splitting the list in two lists - the first one containing the elements on the odd positions and the second list with the elements placed on the even positions, like so:
msort [] = []
msort [x] = [x]
msort xs = merge (msort first) (msort second)
where
(first, second) = splitInHalves xs
splitInHalves [] = ([], [])
splitInHalves [x] = ([x], [])
splitInHalves (x:y:xs) =
let (xs1, ys1) = splitInHalves xs
in (x:xs1, y:ys1)
This gets you the same Merge Sort in O(NlogN) time. It feels different because you would probably implement it in place (by modifying the original list) in an imperative language such as C. This version is slightly more costly on the memory, but it does have it's advantages - it is more easy to reason about, so it is more maintainable, and also it is very easy to parallelize without being concerned of anything else except the algorithm itself - which is exactly what a good programming language should provide for the developers that use it.
EDIT 1 :
If the syntax is a bit much, here are some resources:
Pattern Matching - the bit with the # symbol is called an as-pattern. You'll find it in there
let is a keyword used to declare a variable to be used in the expression that follows it (whereas where binds a variable in the expression that precedes it). More on Haskell syntax, including guards (the things with | condition = value) can be found here, in this chapter of Learn You a Haskell
EDIT 2 :
#is7s proposed a far more concise version of splitInHalves using the foldr function:
splitInHalves = foldr (\x (l,r) -> (x:r,l)) ([],[])
EDIT 3 :
Here is another answer which provides an alternative implementation of merge sort, which also has the property of being stable:
Lazy Evaluation and Time Complexity
Hope this helps and welcome to the wonderful world of Functional Programming !

Using conditionals in Scheme

I have to create the following:
A Scheme procedure named 'proc2' which takes 4 numbers as arguments
and returns the value of the largest argument minus the smallest.
So I want to write
(define proc2
lambda(a b c d)
...
)
Is there any way I can evaluate (> a b), (> a c), (> a d) at the same time? I want to get the largest (and the smallest)number without having to write nested ifs.
Can you use the max and min procedures? if the answer is yes, it's pretty simple:
(- (max a b c d) (min a b c d))
If not, remember that <, >, <=, >= accept a variable number of arguments, so this is valid code and will tell you if a is smaller than b and b is smaller than c and c is smaller than d (although you'll have to test more combinations of b, c, d to make sure that a is the smallest value).
(< a b c d)
Also remember to consider the cases when two or more numbers are equal (that's why it's a good idea to use <= instead of <).
Anyway, you'll have to use conditionals. Maybe nested ifs, or perhaps a cond to make things simpler - you can work out the details yourself, I'm guessing this is homework.
If you want to find the smallest and largest members of the list and you are not allowed to use the standard min and max library functions, then I can think of three approaches
Write your own min and max functions (hint: recursion). Apply both to the list to find your two values. Perform the subtraction.
Write a combined function (again, recursive) which will pass through the list once, returning another two-member list which contains the max and min. If the first element in the returned list is the max, then (apply - (find-min-and-max 3 2 8 7)), where find-min-and-max is your function, would return the result of the subtraction.
Use map.
Option 1 is less efficient than option 2 but much simpler to write. Option 3 is more complex than either but actually does what you asked (that is, compare a to b, c and d "at the same time").
For example, if I defined the following function:
(define (compare test x l)
(map (lambda (y) (test x y)) l))
then
(compare < 3 '(1 2 4))
would return (#f #f #t)
How is this useful to you? Well, if (compare < x l) returns all true, then x is smaller than all elements of l. If it returns all false, then x is bigger than all elements of l. So you could use map to build the code you want, but I think it would be ugly and not the most efficient way to do it. It does do what you specifically asked for, though (multiple simultaneous comparisons of list elements).

Resources