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.
Related
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;;
I try to define function with the following protocol:
[(1,2), (6,5), (9,10)] -> [3, 11, 19]
Here is what I have now:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else (#1 hd(l)) + (#2 hd(l))::sum_pairs(tl(l))
According to type checker I have some type mismatch, but I can't figure out where exactly I'm wrong.
This code runs in PolyML 5.2:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else ((#1 (hd l)) + (#2 (hd l))) :: sum_pairs(tl l)
(* ------------^-------------^ *)
The difference from yours is subtle, but significant: (#1 hd(l)) is different from (#1 (hd l)); the former doesn't do what you think - it attempts to extract the first tuple field of hd, which is a function!
While we're at it, why don't we attempt to rewrite the function to make it a bit more idiomatic? For starters, we can eliminate the if expression and the clunky tuple extraction by matching on the argument in the function head, like so:
fun sum_pairs [] = []
| sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest)
We've split the function into two clauses, the first one matching the empty list (the recursive base case), and the second one matching a nonempty list. As you can see, this significantly simplified the function and, in my opinion, made it considerably easier to read.
As it turns out, applying a function to the elements of a list to generate a new list is an incredibly common pattern. The basis library provides a builtin function called map to aid us in this task:
fun sum_pairs l = map (fn (a, b) => a + b) l
Here I'm using an anonymous function to add the pairs together. But we can do even better! By exploiting currying we can simply define the function as:
val sum_pairs = map (fn (a, b) => a + b)
The function map is curried so that applying it to a function returns a new function that accepts a list - in this case, a list of integer pairs.
But wait a minute! It looks like this anonymous function is just applying the addition operator to its arguments! Indeed it is. Let's get rid of that too:
val sum_pairs = map op+
Here, op+ denotes a builtin function that applies the addition operator, much like our function literal (above) did.
Edit: Answers to the follow-up questions:
What about arguments types. It looks like you've completely eliminate argument list in the function definition (header). Is it true or I've missed something?
Usually the compiler is able to infer the types from context. For instance, given the following function:
fun add (a, b) = a + b
The compiler can easily infer the type int * int -> int, as the arguments are involved in an addition (if you want real, you have to say so).
Could you explain what is happening here sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest). Sorry for may be dummy question, but I just want to fully understand it. Especially what = means in this context and what order of evaluation of this expression?
Here we're defining a function in two clauses. The first clause, sum_pairs [] = [], matches an empty list and returns an empty list. The second one, sum_pairs ((a, b)::rest) = ..., matches a list beginning with a pair. When you're new to functional programming, this might look like magic. But to illustrate what's going on, we could rewrite the clausal definition using case, as follows:
fun sum_pairs l =
case l of
[] => []
| ((a, b)::rest) => (a + b)::sum_pairs(rest)
The clauses will be tried in order, until one matches. If no clause matches, a Match expression is raised. For example, if you omitted the first clause, the function would always fail because l will eventually be the empty list (either it's empty from the beginning, or we've recursed all the way to the end).
As for the equals sign, it means the same thing as in any other function definition. It separates the arguments of the function from the function body. As for evaluation order, the most important observation is that sum_pairs(rest) must happen before the cons (::), so the function is not tail recursive.
I'm working with a custom implementation of vectors as functions whose domain is a finite "index set" of natural numbers, and whose image is of some type on which one can define a maximum, usually real. E.g. I could have a two-dimensional vector v with v 1 = 2.7 and v 3 = 4.2.
On such vectors I'd like to define an "arg max" like operator, which tells me the index of the maximum component, 3 in the example of v above. I'm saying "the" index because the "arg max" like operator will additionally accept a tie-breaking function to be applied to components with values. (The background is bids in auctions.)
I know that Max on finite sets is defined using fold1 (of which I do not yet understand how it works). I tried this, which was accepted in itself, but then didn't work for the other things I wanted to do:
fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_tb N t v = fold1
(λ x y . if (v x > v y) then x (* component values differ *)
else if (v x = v y ∧ t x y) then x (* tie-breaking needed *)
else y) N"
Note that furthermore I would like to prove certain properties of my "arg max" like operator, which will likely require induction. I know that there is the rule finite_ne_induct for induction over finite sets. OK, but I would also like to be able to define my operator in such a way that it can be evaluated (e.g. when trying with concrete finite sets), but evaluating
value "arg_max_tb {1::nat} (op >) (nth [27::real, 42])"
with expected return value 1 gives me the following error:
Wellsortedness error
(in code equation arg_max_tb ?n ?t ?v \equiv
fold1 (\lambda x y. if ord_real_inst.less_real (?v y) (?v x) then ...) ?n):
Type nat not of sort enum
No type arity nat :: enum
Therefore I resorted to converting my finite sets to lists. On lists I have been able to define the operator, and to prove some of its properties (can share the code if it's of interest) by induction using list_nonempty_induct.
The working list-based definition looks as follows:
fun arg_max_l_tb :: "(nat list) ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_l_tb [] t v = 0"
(* in practice we will only call the function
with lists of at least one element *)
| "arg_max_l_tb [x] t v = x"
| "arg_max_l_tb (x # xs) t v =
(let y = arg_max_l_tb xs t v in
if (v x > v y) then x (* component values differ *)
else if (v x = v y ∧ t x y) then x (* tie-breaking needed *)
else y)"
fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_tb N t v = arg_max_l_tb (sorted_list_of_set N) t v"
I didn't succeed to directly define a function over the constructors of a finite set. The following doesn't work:
fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ participant"
where "arg_max_tb {} t b = 0"
| "arg_max_tb {x} t b = x"
| "arg_max_tb (insert x S) t b =
(let y = arg_max_tb S t b in
if (b x > b y) then x
else if (b x = b y ∧ t x y) then x
else y)"
It gives me the error message
Malformed definition:
Non-constructor pattern not allowed in sequential mode.
⋀t b. arg_max_tb {} t b = 0
Could this be because the list constructors are defined as a datatype, whereas finite sets are merely defined as an inductive scheme?
Whatever – do you know of a way of defining this function over finite sets? Either by writing it down directly, or by some fold-like utility function?
Folding over a finite set requires that the result is independent of the order in which the elements of the set are visited, because sets are unordered. Most lemmas about fold1 f therefore assume that the folding operation f is left-commutative, i.e., f a (f b x) = f b (f a x) for all a, b, x.
The function that you supply to fold1 in your first definition does not satisfy this because the tie-breaking function is an arbitrary predicate. For example, take the tie-breaking function %v v'. True. Hence, if you want to stick to this definition, you will have to find sufficient conditions on the tie-breaking first and thread this assumption through all your lemmata.
Your working solution based on a sorted list of the elements avoids this commutatitivity problem. Your last suggestion with pattern matching on {}, {x} and insert x S does not work for two reasons. First, fun can only pattern-match on datatype constructors, so you would have to use function instead; this explains the error message. But then, you also have to prove the equations do not overlap and you will therefore run into the same problem with commutativity again. Additionally, you will not be able to prove termination because S might be infinite.
The well-sortedness error for code generation comes from the setup for fold1. fold1 f A is defined as THE x. fold1Set f A x where fold1Set f A x holds iff x is the result of folding f over A in some order of the elements. To check that all the results are the same, the generated code naively tests for all possible values of x whether fold1Set f A x holds. If it indeed finds just one such value, then it returns that value. Otherwise, it raises an exception. In your case, x is an index, i.e., of type nat which infinitely many values inhabit. Hence, exhaustive testing is not possible. Technically, this translates as nat not being an instance of the type class enum.
Normally, you derive specialised code equations for everything that you define in terms of fold1. See the code generator tutorial on program refinement.
This question really consists of multiple questions.
Defining a function on finite sets
fold / foldl1
The usual recursion combinator is Finite_Set.fold (or fold1). However, to be able to prove anything fold f z S, the result must be independent of the order f is applied to the elements of S.
If f is associative and commutative, you can use Finite_Set.ab_semigroup_mult.fold1_insert and Finite_Set.fold1_singleton to get simp rules for fold1 f S and you should be able to use finite_ne_induct as your induction rule.
Note that the function (I'll call it f) you give to fold1 is only commutative if t is a linear order:
fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_tb N t v = fold1
(λ x y . if (v x > v y) then x (* component values differ *)
else if (v x = v y ∧ t x y) then x (* tie-breaking needed *)
else y) N"
This is not covered by the existing lemmas on fold1, so you either need to prove a generalized variant of Finite_Set.ab_semigroup_mult.fold1_insert or insert an additional tie-breaker, e.g.
else if (v x = v y ∧ ~t x y ∧ ~t y x ∧ x < y) then x
If t is a linear order, you will be able to remove this additional tie-breaker from the simp rules. Note that this additional tie-breaker is basically what you get from using sorted_list_of_set.
THE / SOME
Your arg_max_tb selects one element of a list with certain properties. This can also be defined directly with the constructs THE x. P x or SOME x. P x (choice operators). The former selects the unique element satisfying the property P (if no unique element exists, the result is undefined), the latter selects some element satisfying the property P (if no such element exists, the result is undefined). Both work for infinite lists, too.
These are often preferable if you don't need executable code.
Getting an executable function
Functions defined by recursion (i.e. primrec, fun or function) are executable by default (if all functions used in their definition are executable, too). THE and SOME can in general only be executed for enumerable domains (this is the error message you got from value -- nat is not enumerable, as it is not finite).
However, you can always give an alternative definition of your function to the code generator. See the Tutorial on Function Definitions, in particular the section about refinement.
If you prefer the formulation with choice operators for proving, but also like your function to be executable, the easiest way might to prove that the definitions of arg_max_tb via choice and sorted_list_of_set are equivalent. Then you can use the [code_unfold] predicate to replace the definition by choice with the (executable) definition by sorted_list_of_set
Here's what I've got so far...
fun positive l1 = positive(l1,[],[])
| positive (l1, p, n) =
if hd(l1) < 0
then positive(tl(l1), p, n # [hd(l1])
else if hd(l1) >= 0
then positive(tl(l1), p # [hd(l1)], n)
else if null (h1(l1))
then p
Yes, this is for my educational purposes. I'm taking an ML class in college and we had to write a program that would return the biggest integer in a list and I want to go above and beyond that to see if I can remove the positives from it as well.
Also, if possible, can anyone point me to a decent ML book or primer? Our class text doesn't explain things well at all.
You fail to mention that your code doesn't type.
Your first function clause just has the variable l1, which is used in the recursive. However here it is used as the first element of the triple, which is given as the argument. This doesn't really go hand in hand with the Hindley–Milner type system that SML uses. This is perhaps better seen by the following informal thoughts:
Lets start by assuming that l1 has the type 'a, and thus the function must take arguments of that type and return something unknown 'a -> .... However on the right hand side you create an argument (l1, [], []) which must have the type 'a * 'b list * 'c list. But since it is passed as an argument to the function, that must also mean that 'a is equal to 'a * 'b list * 'c list, which clearly is not the case.
Clearly this was not your original intent. It seems that your intent was to have a function that takes an list as argument, and then at the same time have a recursive helper function, which takes two extra accumulation arguments, namely a list of positive and negative numbers in the original list.
To do this, you at least need to give your helper function another name, such that its definition won't rebind the definition of the original function.
Then you have some options, as to which scope this helper function should be in. In general if it doesn't make any sense to be calling this helper function other than from the "main" function, then it should not be places in a scope outside the "main" function. This can be done using a let binding like this:
fun positive xs =
let
fun positive' ys p n = ...
in
positive' xs [] []
end
This way the helper function positives' can't be called outside of the positive function.
With this take care of there are some more issues with your original code.
Since you are only returning the list of positive integers, there is no need to keep track of the
negative ones.
You should be using pattern matching to decompose the list elements. This way you eliminate the
use of taking the head and tail of the list, and also the need to verify whether there actually is
a head and tail in the list.
fun foo [] = ... (* input list is empty *)
| foo (x::xs) = ... (* x is now the head, and xs is the tail *)
You should not use the append operator (#), whenever you can avoid it (which you always can).
The problem is that it has a terrible running time when you have a huge list on the left hand
side and a small list on the right hand side (which is often the case for the right hand side, as
it is mostly used to append a single element). Thus it should in general be considered bad
practice to use it.
However there exists a very simple solution to this, which is to always concatenate the element
in front of the list (constructing the list in reverse order), and then just reversing the list
when returning it as the last thing (making it in expected order):
fun foo [] acc = rev acc
| foo (x::xs) acc = foo xs (x::acc)
Given these small notes, we end up with a function that looks something like this
fun positive xs =
let
fun positive' [] p = rev p
| positive' (y::ys) p =
if y < 0 then
positive' ys p
else
positive' ys (y :: p)
in
positive' xs []
end
Have you learned about List.filter? It might be appropriate here - it takes a function (which is a predicate) of type 'a -> bool and a list of type 'a list, and returns a list consisting of only the elements for which the predicate evaluates to true. For example:
List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]
Your existing code won't work because you're comparing to integers using the intversion of <. The code hd(l1) < 0 will work over a list of int, not a list of real. Numeric literals are not automatically coerced by Standard ML. One must explicitly write 0.0, and use Real.< (hd(l1), 0.0) for your test.
If you don't want to use filter from the standard library, you could consider how one might implement filter yourself. Here's one way:
fun filter f [] = []
| filter f (h::t) =
if f h
then h :: filter f t
else filter f t
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.