SML type -> type -> type - sml

I'm struggling to understand this. Problem:
I have
datatype 'a tree= Leaf of 'a | Node of 'a tree * 'a * 'a tree
I have to find value in it using binary search. Here's my code.
fun binSearch ((Leaf n), x) = if n=x then true else false
| binSearch ((Node (left, n, right)), x) =
if n=x then true else
if n>x then binSearch (left, x) else
binSearch (right, x)
But I'm supposed to write function with this signature:
val binSearch : int tree -> int -> bool
I get the int tree * int -> bool part, but how do I do 'a -> 'b -> 'c

To turn a function of type a * b -> c into a function of type a -> b -> c, replace fun f (x, y) = ... with fun f x y = ....
fun f (x, y) = ... defines a function that takes a tuple and automatically unpacks the tuple's values into the variables x and y. This is a syntactic short cut for fun f tuple = case tuple of (x, y) => .... It leads to the type a * b -> c because a * b means "a tuple containing an a and a b". The function can then be called as f (x, y) or f t where t is a tuple.
fun f x y = ... on the other hand defines a so-called curried function, which is a function that takes the parameter x and then returns another function, which takes the parameter y and then returns the result. It is a syntactic shortcut for fun f x = fn y => .... The function can then be called as f x y or g y where g has previously been set to f x.

The signature int tree * int -> bool means that the function takes a pair (int tree, int) as input and outputs a bool.
The signature int tree -> int -> bool is equivalent to int tree -> (int -> bool), and means that the function takes an int tree and outputs a function with signature int -> bool.
Signature 'a * 'b -> 'c is obtained this way:
fun my_fun (a,b) = some_c
while signature 'a -> 'b -> 'c is obtained this way:
fun my_fun a = fn b => some_c
That is, you have to create and return a lambda expression (an anonymous function created on the fly).
Also, remember that the first kind of function is called this way: my_fun(my_tree,my_int), while the second kind this other way: my_fun my_tree my_int.

Related

What does f: 'a -> b' -> c' -> d' mean in ocaml?

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.

How to declare an argument as a function in SML?

my question goes like this:
how can I define a function , that receives a function without using type constraints or in other words, without having to type fun f1(f2:type->type) ?
I'm trying to think of a way that uses the argument f2 as a function but its not getting anywhere.
Any ideas?
The one thing that you can do with a function that you can't do with any other value, is to call it. So using f2 as a function means calling it - that is, applying it to an argument.
So for example you could define f1 as:
fun f1 f2 = f2 42
and the inferred type of f1 would be (int -> 'a) -> 'a (making the type of f2 int -> 'a).
By returning an anonymous function, you can do this in such a way that the resulting function can take an arbitrary function for input (although not in a very useful way):
fun id f = fn x => f x
This makes id a higher-order function which returns its input function unmodified. The type of id is fn : ('a -> 'b) -> 'a -> 'b
As an example of its "use":
- fun f x = x*x;
val f = fn : int -> int
- val g = id f;
val g = fn : int -> int
- g 5;
val it = 25 : int
A slightly more interesting example which will only work with functions of type 'a -> 'a:
fun self_compose f = fn x => f (f x)

How to convert CPS-style gcd computation to use the Continuation Monad

Let us consider the following implementation of the Continuation monad, for CPS-style computations yielding and integer:
module Cont : sig
type 'a t = ('a -> int) -> int
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val callCC: (('a -> 'b t) -> 'a t) -> 'a t
end = struct
type 'a t = ('a -> int) -> int
let return x =
fun cont -> cont x
let bind m f =
fun cont -> m (fun x -> (f x) cont)
let callCC k =
fun cont -> k (fun x -> (fun _ -> cont x)) cont
end
How can we rewrite the CPS-style implementation of gcd computation (see How to memoize recursive functions?) and especially the memoization to take advantage of the Cont monad?
After defining
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then Cont.return b else k (b,r)
I tried to use the type solver to give me cue about the type that the memoization function should have:
# let gcd memo ((a,b):int * int) =
Cont.callCC (memo gcd_cont (a,b)) (fun x -> x)
;;
val gcd :
(((int * int -> int Cont.t) -> int * int -> int Cont.t) ->
int * int -> (int -> 'a Cont.t) -> int Cont.t) ->
int * int -> int = <fun>
However I could not turn this hint into an actual implementation. Is someone able to do this? The logic behind using “callCC” in the memoization function is that if a value is found in the cache, then this is is an early exit condition.
I feel like the issue is that in his answer to How to memoize recursive functions?, Michael called CPS style what is not CPS style. In CPS style, the extra continuation argument k is used whenever one wants to return a value - the value is then applied to k instead.
This is not really what we want here, and not what implements:
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then b else k (b,r)
Here, k is not used for returning (b is returned directly), it is used instead of performing a recursive call. This unwinds the recursion: within gcd_cont, one can think of k as gcd_cont itself, just like if let rec was used. Later on, gcd_cont can be turned into a truly recursive function using a fixpoint combinator, that basically "feeds it to itself":
let rec fix f x = f (fix f) x
let gcd = fix gcd_cont
(this is equivalent to the call function that Michael defines)
The difference with defining gcd directly using a let rec is that the version with unwinded recursion allows one to "instrument" the recursive calls, as the recursion itself is performed by the fixpoint combinator. This is what we want for memoization: we only want to perform recursion if the result is not in the cache. Thus the definition of a memo combinator.
If the function is defined with a let rec, the recursion is closed at the same time as defining the function, so one cannot instrument the recursive call-sites to insert memoization.
As a side note, the two answers basically implement the same thing: the only difference is the way they implement recursion in the fixpoint combinator: Michael's fixpoint combinator uses let rec, Jackson's one uses a reference, i.e. "Landin's knot" — an alternative way of implementing recursion, if you have references in your language.
Sooo, to conclude, I'd say implementing that in the continuation monad is not really possible / does not really make sense, as the thing was not CPS in the first place.

Ocaml Type-inference of fun f [x; y; z] -> (f x y), (f z);;

I have this OCaml function:
fun f [x; y; z] -> (f x y), (f z);;
and the teacher wants me to answer: what is the type of this function.
But i do not understand what does [x; y; z] means? Is it a list ? i don't think so because the solution is
('a -> 'a-> 'b) -> 'a list -> b*('a->'b))
and it means that z is of different type and I cannot undestand how do I get it. Is it a vector? a sequence of three inputs? don't think so neither because otherwise it would be
fun f x y z -> (f x y), (f z);;
Can someone help me?
Okay, let's evaluate type of fun f [x; y; z] -> (f x y), (f z) this.
Our function takes to arguments and returns a tuple. So it's type will be _ -> _ -> _ * _ where underscores are not evaluated yet parts. We will evaluate them below
Our 2nd argument is a list , so types of x , y and z are the same.
_ -> 'a list -> _ * _
when we look at 1st expression in result tuple (f x y) we see that f is applied to x and y, so we can rewrite result as:
('a -> 'a -> 'b) -> 'a list -> 'b * _
in second expression in function result expression we see f z. But we already know that f is 'a -> 'a -> 'b already, so it seems that f z has type 'a -> 'b.
('a -> 'a -> 'b) -> 'a list -> 'b * ('a -> 'b)
Et voilà!
This is a list for sure. It cannot be anything else.
Your function accepts two arguments. The first one is a function, and the second is a list, that is deconstructed into three values. The function accepts two arguments. Since all functions in OCaml is currified it can also accept one argument and "return" a function that will accept the other argument and yield a result.
So, at the end you have a pair of a result of an application of function f to the first two elements of a list, and a partial application of the same function to the third element of a list.
Hope, this answers your questions.

Need help understanding currying

Here is an example I picked up from this ebook (http://www.cs.cornell.edu/riccardo/prog-smlnj/notes-011001.pdf)
-fun curry (f:'a * 'b -> 'c) = fn (x:'a) => fn (y:'b) => f (x,y);
val curry = fn : ('a * 'b -> 'c) -> 'a -> 'b -> 'c
How do I interpret this function. Curry takes as argument a function f of type 'a * 'b -> 'c. I can't understand the part after '='. What is the associativity order?
Here is another example:
fun add’ (x:int) (y:int):int = x + y;
How is this parsed?
Wikipedia says "currying is the technique of transforming a function that takes multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions each with a single argument (partial application)". Which is the single argument: the first or the last one out of the multiple arguments?
fn (x:'a) => fn (y:'b) => f (x,y) is parsed as fn (x:'a) => (fn (y:'b) => f (x,y)). So you have a function, which takes an argument x of type a and returns another function, which takes an argument y of type b. This other function then returns the result of calling f (x,y).
fun foo x y = ... is syntactic sugar for val foo = fn x => fn y => ..., so again foo is a function, which takes one argument x and returns another function, which takes one argument y.
Similarly the call foo 1 2 will be parsed as (foo 1) 2, i.e. it calls the function foo with the argument 1 and then calls the resulting function with the argument 2.