I referenced codes in this question: How to implement a dictionary as a function in OCaml?, and I wrote my code of functional dictionary in OCaml:
type key = string;;
type 'a dict = key -> 'a option;;
let add (d : 'a dict) (k, v) : 'a dict = fun k' -> if k' = k then v else d k';;
let empty () = ... ;;
let find d k = ... ;;
In this code, what I want to know is how the add function works. What does the variable k' mean? When we use fun keyword, for example, let sub x = fun y -> x - y;;, the variable that comes next to the fun means an argument. Is it right? When I want to use the sub function I defined, we can call the function with
# sub 1 2;;
- : int = -1
and 2 is an argument that is bound to y, which is the variable next to the fun keyword. However, in the dictionary code above, there is the variable k' in the add function, next to the fun keyword, but it does not represent any additional argument. Arguments that are needed to call the add function is a 'a dict type variable and a (k, v) type tuple. No third argument is required. Then, what does the k' mean? I have no idea.
In OCaml,
let sub x y = x - y
is a shorthand notation (the syntactic sugar) for
let sub = fun x -> fun y -> x - y
To get it, let's pick an even simpler example,
let succ x = x + 1
is the shorter syntactic form for
let succ = fun x -> x + 1
which says that we bind the name succ to a function fun x -> x + 1, where the latter is the function literal. A literal in programming languages is the syntactic notation for defining values. For example, for integers we have a finite set of literals 1, 2, 3, etc. For strings, we have a practically infinite set of literals, e.g., "hello", "", "etc". A function in OCaml is also a value, the same as an integer or a string, therefore it has a syntax for function literals, which is
fun <arg> -> <body>
It creates a function, that evaluates to the value of <body> in which all free occurrences of <arg> are substituted be the actually passed parameter.
As you probably noticed, we could really bind only one parameter in the function literal. Indeed, all functions in OCaml are unary. You may already know that you can define functions like fun x y -> x - y, but this is also just syntactic sugar for fun x -> fun y -> x - y. So what the latter notation means? Let's ascribe parenthesis to get the idea of how this function is evaluated:
fun x -> (fun y -> x - y)
So we can recognize the fun x -> <body> part, where <body> is a function on itself, i.e., <body> = fun y -> x - y. That means that expression fun x -> fun y -> x - y is a function, that takes an argument x and returns another function, that takes an argument y and returns x-y. This way of defining functions, i.e., when instead of having functions that accept tuples you have a function that returns a function and so on, is called currying.
Now, when we are comfortable with the idea of currying and that all functions in OCaml are really of one argument, we can go back to the original example of the functional dictionaries.
The add function
let add (d : 'a dict) (k, v) : 'a dict = fun k' -> if k' = k then v else d k'
stripped of the (unnecessary) type annotations
let add d (k, v) = fun k' -> if k' = k then v else d k'
and then represented in the form that makes currying explicit, is
let add = fun d -> fun (k, v) -> fun k' -> if k' = k then v else d k'
So it is a function that for given dictionary d produces a function that takes a pair (k,v) and returns a function that for all k' that are equal to k will return d. And if keys are different, then it applies the key to the first parameter d. Let's take a deeper look at the
fun k' -> if k' = k then v else d k'
literal. As we can see variables d and k occur free in that function, i.e., they are not bound by the parameter k. When a function references a variable from the outer scope (which is not defined on the module level), a closure is created. A closure is an opaque object that contains a pointer to the code1 (in our case it is if k' = k then v else d k' and pointers to each captured variable (i.e., to each variable that is taken from the outer scope). In our case, it creates (roughly) a record that has three entries, d, k and the code. After a few hours of mediation, it is not hard to see, that a function dictionary is just singly-linked list of closures, as d is a pointer to the closure, which, in turn, contains a pointer to another closure, until we reach the pointer to empty, which returns None no matter the key (and is coded incorrectly in your example, as it should expect any key, not for the value of type unit).
With all that said and kept in mind, we can now write the short-hand notation for the add function:
let add d k k' = if k' = k then v else d k'
which has absolutely the same semantics (i.e., meaning, behavior) as any other notations, as it is just the syntactic sugar.
1)To prevent any confusion, the code itself is never stored in the heap memory. Even when you have an anonymous function that is not bound to any name, e.g., (fun x y -> x + y) 2 3 the compiler will emit the code and store it in the text section of a binary and give it some funny name. So the code above will be just a normal call to a function with mangled name, e.g., call Testing_fun001. And going back to the functional dictionary example, each entry will be an object with three words, the key, the data, the pointer to the next entry. Basically the same underlying representation as an association list.
About your type definitions..
type key = string;;
type 'a dict = key -> 'a option;;
Why not...
type 'a dict = 'a -> 'a option;;
Or even better...
type ('a, 'b) dict = 'a -> 'b option;;
Related
If I have a function f defined as
f: 'a -> 'b -> c' -> d'
Does that mean it takes one argument? Or 3? And then it outputs one argument? How would I use or call such a function?
As Glennsl notes in the comments, it means both.
Very briefly, and by no means comprehensively, from an academic perspective, no function in OCaml takes more than one argument or returns more or less than one value. For instance, a function that takes a single argument and adds 1 to it.
fun x -> x + 1
We can give that function a name in one of two ways:
let inc = fun x -> x + 1
Or:
let inc x = x + 1
Either way, inc has the type int -> int which indicates that it takes an int and returns an int value.
Now, if we want to add two ints, well, functions only take one argument... But functions are first class things, which means a function can create and return another function.
let add =
fun x ->
fun y -> x + y
Now add is a function that takes an argument x and returns a function that takes an argument y and returns the sum of x and y.
We could use a similar method to define a function that adds three ints.
let add3 =
fun a ->
fun b ->
fun c -> a + b + c
The type of add would be int -> int -> int and add3 would have type int -> int -> int -> int.
Of course, OCaml is not purely an academic language, so there is convenience syntax for this.
let add3 a b c = a + b + c
Inferred types
In your question, you ask about a type 'a -> 'b -> 'c -> 'd``. The examples provided work with the concrete type int. OCaml uses type inferencing. The compiler/interpreter looks at the entire program to figure out at compile time what the types should be, without the programmer having to explicitly state them. In the examples I provided, the +operator only works on values of typeint, so the compiler _knows_ incwill have typeint -> int`.
However, if we defined an identity function:
let id x = x
There is nothing her to say what type x should have. In fact, it can be anything. But what can be determined, if that the function will have the same type for argument and return value. Since we can't put a concrete type on that, OCaml uses a placeholder type 'a.
If we created a function to build a tuple from two values:
let make_tuple x y = (x, y)
We get type 'a -> 'b -> 'a * 'b.
In conclusion
So when you ask about:
f: 'a -> 'b -> 'c -> 'd
This is a function f that takes three arguments of types 'a, 'b, and 'c and returns a value of type 'd.
I have tried to write code but this only returns max value and not the absolute.
let rec maxAbsolutenumber_L l =
match l with
|[] -> None
|x::_ -> x
|x::xs -> max x (max_number_list xs)
Imagine you had a function like max except it returns whichever of the two values has the largest absolute value. Seems like that would solve your problem.
You can start, then, by writing this function.
As a side comment, it is not legitimate to return None for some calls to a function and an integer value for other calls. They aren't the same type.
As another side comment, the second case of your match will match all nonempty lists. I think you want it to match only lists of length 1. The pattern for such a list is [x] (or you can use x :: [], which is equivalent).
Update
Here is the basic structure for defining a function that has another (helper) function inside:
let myfunc a b =
let helper x y =
(* Definition of helper *)
in
(* Definition of myfunc with calls to helper *)
Here's a concrete example, a function that returns the longest string in its input list:
let longest_string strings =
let max_string a b =
if String.length a >= String.length b then a else b
in
List.fold_left max_string "" strings
Here is an implementation of the usual max function, which might give you some ideas for writing similar functions:
let max a b =
if a >= b then a else b
Problem:Define the function mapf whose first argument is a unary function, and second argument list. The result is a list of the function applied to each element of the argument list. Write a one-liner using fold_right, and not a recursive function.
Solution:
let mapf fn list = fold_right (fun h t -> fn h :: t) list []
I don't understand how that solves the problem because fold_right computes a function with the list arguments in a recursive way, so it returns a value and not a list. I neither understand what the following notation means:
fun h t -> fn h :: t
Your two questions are related. It's true that fold_right returns a value, but a list is a value!
The :: operator adds a new element to the beginning of a list. So the value computed by this application of fold_right is indeed a list.
Another way to think of this might be as follows. If you use fold_right with the + operator you compute a value like so:
fold_right (+) [1; 2; 3] 0 =>
1 + 2 + 3 + 0 =>
6
If you use fold_right with the :: operator, you compute a value like so:
fold_right (::) [1; 2; 3] [] =>
1 :: 2 :: 3 :: [] =>
[1; 2; 3]
This isn't theoretical, it works exactly like this in the REPL:
# List.fold_right (+) [1; 2; 3] 0;;
- : int = 6
# List.fold_right (fun a b -> a :: b) [1; 2; 3] [];;
- : int list = [1; 2; 3]
(You need to write fun a b -> a :: b because the :: notation can't actuallly be used as a stand-alone function. Unfortunately.)
Note that it's completely legitimate to write a list using the :: operator yourself:
# 1 :: 2 :: 3 :: [];;
- : int list = [1; 2; 3]
Update
First, fun x y -> expr is the notation for a "lambda" in OCaml, i.e., for a function literal.
The function fun h t -> fn h :: t takes two values h and t. It applies the function fn to h, and returns a new list with this new value at the front of t.
From a typing standpoint, the value h must be the right type to pass to fn, and fn must return a value of the right type to be in the list t.
You could parenthesize it like this: fun h t -> (fn h) :: t, if that makes it clearer.
The function fun a b -> a :: b is similar except that it just puts a directly onto the list b. It doesn't apply any function. In essence, it does just what the :: operator does.
From a typing standpoint, a has to be the right type to be an element of the list b.
Update 2
If you're trying to understand what a lambda is, one way of looking at it is that it's just a handy way to write a function that's reasonably small. You can easily write your given code without the lambda:
let mapf fn list =
let helper h t = fn h :: t in
List.fold_right helper list []
Instead of a lambda, this version has a locally declared function named helper.
Another way of looking at it is that all functions are lambdas. The idiomatic way of writing a function:
let f x y = x + y
is just a handy abbreviation for a version with an explicit lambda:
let f = fun x y -> x + y
So, really, a lambda isn't a special kind of function. It's exactly like any other function. It's just a notational choice.
So I have a function r which is supposed to apply a function to every element in the list provided it meets a given predicate, and return that list. i.e.
let p x = x > 2;;
let f x = x+1;;
r p f [1;2] => []
I am using a map function that applies a function to every element in a list and then returns that list. Thus my implementation for r is as follows
let r f p l = map f (map (fun x -> if (p x) then x) l );;
but if I attempt to call r like in the example above I get a type error because f and p are expressions for ints and it expected expression for units. Where did I go wrong?
First of all let me explain, why unit comes into play.
In OCaml if/then/else is not a statement, it is an expression, like ternary operator in C-like languages or like conditional expression in Python. Than means, that being an expression it always must have a value. You cannot just give an expression for the true branch, and omit the else branch, unless the value to the else branch is trivial and always known to a compiler. And the latter is only possible for the unit type. Since this type is inhabited with only one value, then if you true branch returns a value of type unit, compiler already knows what would return the false branch. That's why you can omit else part of the expression, that evaluates to unit. And the omission of the else part is satisfactory proof for the compiler that the whole expression has type unit. That means, that in expression if (p x) then x, compiler decided that x has type unit, because there is no else part.
Now to the task. map must return a value for each element of the list. It cannot skip or rearrange, or change the structure. For this there're other higher order functions called filter_map, concat_map, filter, etc.
But lets try to do something without leaving the original wording. So back to your example, we need do something in the else part. What we should return to designate that there is no value? We can return None that is a value of type option, e.g.,
if p x then Some x else None
Notice, that we also need to lift the then part to the option type. As a result we will have a list of type 'a option list. Then we need to filter it, removing Nones.
Other choice is to return an empty list (aka nil), instead of None:
if p x then [x] else []
Then we will have a 'a list list that can be easily transformed to 'a list with concat operation. Moreover, we can notice, that there is no need to create an intermediate list, we can apply f just in place (i.e., there is an opportunity for deforesting optimization here):
if p x then [f x] else []
And finally we have:
let r f p l = concat (map (fun x -> if p x then [f x] else []) l)
Later, you will discover, that both option and list are monads, and this trick with map and concat is actually the core operation for all monads, called bind and denoted as >>=. With this operator defined, we can write r function more elegantly:
let r f p l = l >>= fun x -> if p x then [f x] else []
where the bind operator can be implemented (inefficiently), as
let (>>=) x f = concat (map f x)
But this all was functional mumbo-jumbo, practically, it is better just to use fold_left (as Jeffrey suggested), and accumulate your result in an auxiliary list, without forgetting to reverse it:
let r f p l = rev (fold_left (fun xs x -> if p x then f x :: xs else xs) [] l)
And in real-world programming, you will be using the standard library functions such as List.filter_map or List.concat_map for that.
The map function applies a function to every element of a list and returns the list of results. It always returns a list of equal length to the input list. So your problem statement doesn't make complete sense.
At a lower level, the expression if (p x) then x is only legitimate if x has type unit. I.e., the meaning of if b then e is the same as if b then e else (), and both sides of the if have to be the same type.
If you want to return a list of a different length than your input list, you'll need to use a fold function rather than map.
For instance, i have a list like ['a','b','c','d','e'].
I want to do something like this:
First do something with the first two elements, f 'a' 'b'
Then do the same thing with the return value of f and next element in the list, result = f 'a' 'b', lets say like f result 'c'. Then f resultof(result 'c') 'd' and so on.
How can i do something like this?
First let's consider that function f that you have. It takes some sort of accumulated value, a plain value, and combines them into a result. So, in the type signature, we'll say a for the type of the accumulated value, v for the type of the value, and r for the type of the result.
f :: a -> v -> r
Now we want to create a folding function that uses f and a list of values.
someFold :: (a -> v -> r) -> [v] -> ?
What should it return? It should yield something of the resultant type r, right? Notice now that a and r should actually be the same type, since we keep feeding the result of f into it's first argument again.
someFold :: (a -> v -> a) -> [v] -> a
Now one thing's missing. How do you get the very first a? There are two ways to look at that. Either you just pick the first value, in which case a is the same type as v, or you specify a base value, so a could actually be different than v. Let's go with the latter, since that's more interesting. Let's also decide to move left to right in this list. (That's what you need, right?)
someFold :: (a -> v -> a) -> a -> [v] -> a
So...how do we implement it? It'll be recursive, so let's start with the base cases.
someFold f acc [] = acc
If we hit the end of the list, then we've accumulated enough, right? That was easy. So how about the recursive case? From what you said, at each step we should apply f to the "accumulated value so far" as the first argument, and the "first value of the list" as the second. f acc x. Then we keep folding, using that as our new "accumulated" value.
someFold f acc (x:xs) = someFold f (f acc x) xs
Easy, right? But...what if we want to do like you said and start the function by taking the first two values of the list? Also easy. Just take the first element, and call it the original "base" accumulator!
someFold1 :: (v -> v -> v) -> [v] -> v
someFold1 f (x:xs) = someFold f x xs
Notice that since a is the same type as v for this special case, the function someFold1 has a very amusing type signature. If you understood this explanation, then congrats. We've just implemented foldl and foldl1.
Prelude> foldl1 min "abcde" -- "abcde" is sugar for ['a','b','c','d','e']
'a'
In real code, you should actually use foldl' and friends.
Sounds like homework. Take a look at folds.
In this case, the problem with a fold is, that it usually processes on element at a time. You could try to manually roll a fold.
Assume, you have your function f, that gets two elements at a time and the accumulator (the result of the last iteration) fed. Then you function looks like this:
fold2 :: (a -> a -> b -> b) -> [a] -> b -> b
fold2 f accum (x:y:zs) = fold2 f (f x y) zs
fold2 _ accum [] = accum
fold2 _ _ _ = error "odd number of elements"
Try to understand this. fold2 shaves the top two elements of the list of and feeds it into f. The result this is then passed as the new accumulator to the recursive call. This is done until the list is empty.