I am trying to figure out how exactly does treesort from here work (I understand flatten, insert and foldr).
I suppose what's being done in treesort is applying insert for each element on the list thus generating a tree and then flattening it. The only problem I can't overcome here is where the list (that is the argument of the function) is hiding (because it is not written anywhere as an argument except for the function type declaration).
One more thing: since dot operator is function composition, why is it an error when I change: treesort = flatten . foldr insert Leaf to treesort = flatten( foldr insert Leaf )?
what's being done in treesort is applying insert for each element on the list thus generating a tree and then flattening it.
Exactly right.
[Where is the list hiding?]
In a functional language, you don't have to give the arguments of a value of function type. For example if I write
f = concat . map (map toUpper)
I get a function of type [[Char]] -> [Char]. This
function expects an argument even though there's no argument in the defining equation.
It's exactly the same as if I had written
f strings = (concat . map (map toUpper)) strings
Since the dot operator is function composition, why is it wrong to change f . g to f (g)?
They don't mean the same thing. What happens when each is applied to x?
(f . g) x = f (g x)
(f (g)) x = (f g) x
You can see the applications associate differently, and f. g is different from f g.
It's a type error because foldr insert Leaf is a function from lists to trees, and flatten is meant to be applied to a single tree, not to a function.
To answer your last question first, you're getting an error because . is a function composition operator that takes two functions (in this case flatten and foldr insert Leaf). If you want to rewrite the code without the use of ., you'll need to create a function that takes some parameter:
-- // Pass the 'list' to the first function and the
-- // result of the call to the second function
treesort list = flatten (foldr insert Leaf list)
This also explains where the list parameter was hiding. When composing functions, you don't need to write parameters explicitly, because the result of the expression f . g is a function that takes some parameter, calls g and then calls f:
-- // function composition..
composed = f . g
-- // ..is equivalent to declaring a function:
composed x = f (g x)
Sometimes, as long as you are not familiar with the pointless style, it is useful to do epsilon-conversion mentally.
If f is an expression with function type, then one can convert it to
\e -> (f) e
And, if we have a definition like
a = \e -> (f) e
we can always safely rewrite it as
a e = (f) e
Thus
treesort = flatten . foldr insert Leaf
is the same as
treesort list = (flatten . foldr insert Leaf) list
Related
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.)
I'm new to functional programming and I'm trying to implement a basic algorithm using OCAML for course that I'm following currently.
I'm trying to implement the following algorithm :
Entries :
- E : a non-empty set of integers
- s : an integer
- d : a positive float different of 0
Output :
- T : a set of integers included into E
m <- min(E)
T <- {m}
FOR EACH e ∈ sort_ascending(E \ {m}) DO
IF e > (1+d)m AND e <= s THEN
T <- T U {e}
m <- e
RETURN T
let f = fun (l: int list) (s: int) (d: float) ->
List.fold_left (fun acc x -> if ... then (list_union acc [x]) else acc)
[(list_min l)] (list_sort_ascending l) ;;
So far, this is what I have, but I don't know how to handle the modification of the "m" variable mentioned in the algorithm... So I need help to understand what is the best way to implement the algorithm, maybe I'm not gone in the right direction.
Thanks by advance to anyone who will take time to help me !
The basic trick of functional programming is that although you can't modify the values of any variables, you can call a function with different arguments. In the initial stages of switching away from imperative ways of thinking, you can imagine making every variable you want to modify into the parameters of your function. To modify the variables, you call the function recursively with the desired new values.
This technique will work for "modifying" the variable m. Think of m as a function parameter instead.
You are already using this technique with acc. Each call inside the fold gets the old value of acc and returns the new value, which is then passed to the function again. You might imagine having both acc and m as parameters of this inner function.
Assuming list_min is defined you should think the problem methodically. Let's say you represent a set with a list. Your function takes this set and some arguments and returns a subset of the original set, given the elements meet certain conditions.
Now, when I read this for the first time, List.filter automatically came to my mind.
List.filter : ('a -> bool) -> 'a list -> 'a list
But you wanted to modify the m so this wouldn't be useful. It's important to know when you can use library functions and when you really need to create your own functions from scratch. You could clearly use filter while handling m as a reference but it wouldn't be the functional way.
First let's focus on your predicate:
fun s d m e -> (float e) > (1. +. d)*.(float m) && (e <= s)
Note that +. and *. are the plus and product functions for floats, and float is a function that casts an int to float.
Let's say the function predicate is that predicate I just mentioned.
Now, this is also a matter of opinion. In my experience I wouldn't use fold_left just because it's just complicated and not necessary.
So let's begin with my idea of the code:
let m = list_min l;;
So this is the initial m
Then I will define an auxiliary function that reads the m as an argument, with l as your original set, and s, d and m the variables you used in your original imperative code.
let rec f' l s d m =
match l with
| [] -> []
| x :: xs -> if (predicate s d m x) then begin
x :: (f' xs s d x)
end
else
f' xs s d m in
f' l s d m
Then for each element of your set, you check if it satisfies the predicate, and if it does, you call the function again but you replace the value of m with x.
Finally you could just call f' from a function f:
let f (l: int list) (s: int) (d: float) =
let m = list_min l in
f' l s d m
Be careful when creating a function like your list_min, what would happen if the list was empty? Normally you would use the Option type to handle those cases but you assumed you're dealing with a non-empty set so that's great.
When doing functional programming it's important to think functional. Pattern matching is super recommended, while pointers/references should be minimal. I hope this is useful. Contact me if you any other doubt or recommendation.
I've got a library which implements a set (interface with documentation available here: http://pastebin.com/j9QUyN1G). I understand everything apart from this fragment:
val iter : ('a -> unit) -> 'a t -> unit
(** [iter f s] applies [f] to all elements in set [s]. The elements
are passed to [f] in increasing order with respect to the ordering
used to create the set. *)
So iter takes a function as one of the arguements and applies it to all elements of set. So I would expect something like ('a -> 'a) which takes an element of the set and changes it to element of the same type with other value or ('a -> 'b) which takes 'a t and transforms it to 'b t. But instead iter takes a function of type ('a -> unit) and also returns unit, not an 'a t nor 'b t.
So how should an example function passed to iter look like?
iter doesn't change the elements of the set. It's executed purely for its side effects. You might use it to print the elements, for example:
module StringSet = Set.Make(String)
…
StringSet.iter print_endline ss
The set data structure is immutable, so you can't change the elements of the set. You can build a new set whose elements are derived from an existing set. For a list, there's the function map which takes a list [x1; …; xn] and returns a new list [f x1; …; f xn]. There is no similar function in the Set module because elements in a set are not stored in the order chosen by the caller: there's no such thing as a set with its elements in an order derived from another set. If you want to build a set from the images of the elements of a set, insert the new elements one by one.
module Int = struct
type t = int
let compare = Pervasives.compare
end
module IntSet = Set.Make(Int)
module StringSet = Set.Make(String)
let int_to_string_set is =
IntSet.fold (fun i ss -> StringSet.add (string_of_int i) ss) is StringSet.empty
iter takes such function that accepts argument of type 'a do with it whatever it whats and returns a value of type unit. In other words it is evaluated for the side-effects since it can't return anything worthwhile.
What you're looking for is a map function, that usually accepts a function of type 'a -> 'b a container with elements of type 'a and returns an container with elements of type 'b. Unfortunately to you, the interface you've shown, doesn't provide such function. But this is not a problem, since it provides a fold function, that is the most general iterator. Having only fold you can implement any other iteratos, like map, iter, exists, etc... Indeed in Core library you can find Container.Make functor that will automatically derive a common container interface from only one function - fold. But also, you can define map by yourself:
let map f xs =
fold (fun x ys -> add (f x) ys) xs empty
It would be a function with side effects, like this:
Let p x = Printf.printf "%d\n" x
We have a definition of binary tree:
type 'a tree =
| Node of 'a tree * 'a * 'a tree
| Null;;
And also a helpful function for traversing the tree"
let rec fold_tree f a t =
match t with
| Null -> a
| Node (l, x, r) -> f x (fold_tree f a l) (fold_tree f a r);;
And here is a "magic" function which, when given a binary tree, returns a list in which we have lists of elements on particular levels, for example, when given a tree:
(source: ernet.in)
the function returns [[1];[2;3];[4;5;6;7];[8;9]].
let levels tree =
let aux x fl fp =
fun l ->
match l with
| [] -> [x] :: (fl (fp []))
| h :: t -> (x :: h) :: (fl (fp t))
in fold_tree aux (fun x -> x) tree [];;
And apparently it works, but I can't wrap my mind around it. Could anyone explain in simple terms what is going on? Why does this function work?
How do you combine two layer lists of two subtrees and get a layer list of a bugger tree? Suppose you have this tree
a
/ \
x y
where x and y are arbitrary trees, and they have their layer lists as [[x00,x01,...],[x10,x11,...],...] and [[y00,y01,...],[y10,y11,...],...] respectively.
The layer list of the new tree will be [[a],[x00,x01,...]++[y00,y01,...],[x10,x11,...]++[y10,y11,...],...]. How does this function build it?
Let's look at this definition
let rec fold_tree f a t = ...
and see what kind of arguments we are passing to fold_tree in our definition of levels.
... in fold_tree aux (fun x -> x) tree []
So the first argument, aux, is some kind of long and complicated function. We will return to it later.
The second argument is also a function — the identity function. This means that fold_tree will also return a function, because fold_tree always returns the same type of value as its second argument. We will argue that the function fold_tree applied to this set of arguments takes a list of layers, and adds layers of a given tree to it.
The third argument is our tree.
Wait, what's the fourth argument? fold_tree is only supposed to get tree? Yes, but since it returns a function (see above), that function gets applied to that fourth argument, the empty list.
So let's return to aux. This aux function accepts three arguments. One is the element of the tree, and two others are the results of the folds of the subtrees, that is, whatever fold_tree returns. In our case, these two things are functions again.
So aux gets a tree element and two functions, and returns yet another function. Which function is that? It takes a list of layers, and adds layers of a given tree to it. How it does that? It prepends the root of the tree to the first element (which is the top layer) of the list, and then adds the layers of the right subtree to the tail of the list (which is all the layers below the top) by calling the right function on it, and then adds the layers of the left subtree to the result by calling the left function on it. Or, if the incoming list is empty, it just the layers list afresh by applying the above step to the empty list.
This is part of a homework assignment so my goal is to understand why this is wrong. As I mentioned before I'm using Moscow ML.
fun filter pred = let
fun f ([], a) = []
| f ([], a) = a
| f (e::L, a) = if pred e then (f L (e::a) ) else (f L a)
in
f
end
The error I get is:
| f (e::L, a) = if pred e then (f L (e::a) ) else (f L a)
^
Type clash: expression of type
'a list cannot have type
'a list * 'b list
I have been reading up on documentation, and it really hasn't helped. What I really don't get is where 'b list is coming from. In our assignment we have to use an accumulator with tail recursion. I believe where my error is is how filter calls the function f. Filter takes the predicate as an argument and f should take the list and accumulator which is initially the empty list.
I've tried calling f like: f L [], But in other examples we didn't actually have to call f with its argument and it was somehow passed automatically.
Anyway, any help understanding where my mistake is and guidance on how to fix the problem would be greatly appreciated.
-aitee
(also if anyone could give me any tips on decoding the type expression errors that could also be very beneficial.)
(f L (e::a)) would work only if f were a curried function, of type 'a list -> 'a list -> 'a list. You should be doing:
if pred e then (f (L, (e::a))) else (f (L,a))
Btw., SMLNJ complains of a redundant match (two f ([], a) clauses are given).
You're confusing tupled versus curried function calls. Your definition of f demands a tuple, (a,b), but you're passing it arguments as f a b. Try replacing your recursive calls to f L ... with f (L,...) instead.
The type error is a little unhelpful, but it's basically saying that you're passing a list when it expects a 2-tuple of lists.