How do we write Recursive function in SML? - sml

Here is the python code for the recursive function I am implementing.
def f(x):
return x+1
def iter(n, f,x):
if n == 0:
return x
return iter(n-1, f, f(x))
Calling iter
iter(7, f, 9)
How do I write it in SML?
fun iter 0 f x = x
|iter n f x = iter(n-1, f, f(x));

The syntax is:
fun iter 0 f x = x
| iter n f x = iter (n-1) f (f x);
Note: you can replace f by _ at line 1 since f does not appear in the resulting expression.

OP code is mixing curried function notation with tuple notation. The OP defines a curried function, but then passes a tuple to it in the recursive call. There are two obvious solutions: decide whether curried notation or tuple notation is desired, and use that consistently.
With tuple notation iter takes a tuple containing the arguments, i.e., here iter really only takes one argument which is a data type that contains parameters. That is, tuple iter has type: fn : int * ('a -> 'a) * 'a -> 'a
fun iter (0, _, x) = x
| iter (n, f, x) = iter(n-1, f, f x);
The above could be expressed a bit differently, e.g., iter((n-1), f, (f x)), or iter((n-1), f, f(x)).
With the curried notation iter takes a single int argument and returns a function that takes a function argument, returning a function which takes an argument matching the passed function. That is, curried iter has type fn : int -> ('a -> 'a) -> 'a -> 'a.
fun iter 0 _ x = x
| iter n f x = iter (n-1) f (f x);
The tuple version and the curried version are two distinctly different situations. With the tuple version, if you pass fewer than three "arguments" you have a type error, e.g., something like:
- iter(2, double);
stdIn:1.2-1.17 Error: operator and operand do not agree [tycon mismatch]
operator domain: int * ('Z -> 'Z) * 'Z
operand: 'Y[INT] * (int -> int)
in expression:
iter (2,double)
The problem is that the tuple version expects a tuple argument that contains three fields. Passing a tuple with fewer than three fields violates this expectation.
But with the curried version, if you pass fewer than three arguments you have a partial function application:
- val doubleTwice = iter 2 double;
val doubleTwice = fn : int -> int
- doubleTwice 3;
val it = 12 : int
- doubleTwice 5;
val it = 20 : int
Here, passing only two arguments to the curried iter, one of them a double function that doubles an int, returns a function that doubles an input value twice. Curried functions can be very useful, and you need to learn the difference between these two styles.

Related

Understanding the mechanics of fold_right

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.

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.

Cartesian (outer) product of lists in OCaml

I would like to iterate over all combinations of elements from a list of lists which have the same length but not necessarily the same type. This is like the cartesian product of two lists (which is easy to do in OCaml), but for an arbitrary number of lists.
First I tried to write a general cartesian (outer) product function which takes a list of lists and returns a list of tuples, but that can't work because the input list of lists would not have elements of the same type.
Now I'm down to a function of the type
'a list * 'b list * 'c list -> ('a * 'b * 'c) list
which unfortunately fixes the number of inputs to three (for example). It's
let outer3 (l1, l2, l3) =
let open List in
l1 |> map (fun e1 ->
l2 |> map (fun e2 ->
l3 |> map (fun e3 ->
(e1,e2,e3))))
|> concat |> concat
This works but it's cumbersome since it has to be redone for each number of inputs. Is there a better way to do this?
Background: I want to feed the resulting flat list to Parmap.pariter.
To solve your task for arbitrary ntuple we need to use existential types. We can use GADT, but they are close by default. Of course we can use open variants, but I prefer a little more syntactically heavy but more portable solution with first class modules (and it works because GADT can be expressed via first class modules). But enough theory, first of all we need a function that will produce the n_cartesian_product for us, with type 'a list list -> 'a list list
let rec n_cartesian_product = function
| [] -> [[]]
| x :: xs ->
let rest = n_cartesian_product xs in
List.concat (List.map (fun i -> List.map (fun rs -> i :: rs) rest) x)
Now we need to fit different types into one type 'a, and here comes existential types, let's define a signature:
module type T = sig
type t
val x : t
end
Now let's try to write a lifter to this existential:
let int x = (module struct type t = int let x = x end : T)
it has type:
int -> (module T)
Let's extend the example with few more cases:
let string x = (module struct type t = string let x = x end : T)
let char x = (module struct type t = char let x = x end : T)
let xxs = [
List.map int [1;2;3;4];
List.map string ["1"; "2"; "3"; "4"];
List.map char ['1'; '2'; '3'; '4']
]
# n_cartesian_product xxs;;
- : (module T) list list =
[[<module>; <module>; <module>]; [<module>; <module>; <module>];
[<module>; <module>; <module>]; [<module>; <module>; <module>];
...
Instead of first class modules you can use other abstractions, like objects or functions, if your type requirements allow this (e.g., if you do not need to expose the type t). Of course, our existential is very terse, and maybe you will need to extend the signature.
I used #ivg 's answer but in a version with a GADT. I reproduce it here for reference. In a simple case where only the types float and int can appear in the input lists, first set
type wrapped = Int : int -> wrapped | Float : float -> wrapped
this is a GADT without type parameter. Then
let wrap_f f = Float f
let wrap_i i = Int f
wrap types into the sum type. On wrapped value lists we can call n_cartesian_product from #ivg 's answer. The result is a list combinations: wrapped list list which is flat (for the present purposes).
Now to use Parmap, i have e.g. a worker function work : float * int * float * float -> float. To get the arguments out of the wrappers, I pattern match:
combinations |> List.map (function
| [Float f1; Int i; Float f2; Float f3] -> (f1, i, f2, f3)
| _ -> raise Invalid_argument "wrong parameter number or types")
to construct the flat list of tuples. This can be finally fed to Parmap.pariter with the worker function work.
This setup is almost the same as using a regular sum type type wrapsum = F of float | I of int instead of wrapped. The pattern matching would be the same; the only difference seems to be that getting a wrong input, e.g. (F 1, I 1, F 2.0, F, 3.0) would be detected only at runtime, not compile time as here.

SML type -> type -> type

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.

what are curry and uncurry in high-order functions in ML

fun curry f x y = f (x, y);
fun uncurry f (x, y) = f x y;
fun compose (f, g) x = f (g x);
I understand compose function, but not quite understand curry and uncurry in ML. Can anyone explain these?
Also, what do the following two lines mean?
(1) compose (compose, uncurry compose)
(2) compose (uncurry compose, compose)
If you look at the types, then you will clearly see what curry and uncurry does.
Remember that it is possible to define function which either takes its arguments as one big tuple, or as multiple arguments (in reality it becomes a "chain" of functions each taking 1 argument, see this wiki):
fun foo (a,x) = a*x+10
fun bar a x = a*x+20
The difference is clearly seen in their types:
val foo = fn : int * int -> int
val bar = fn : int -> int -> int
The curry function "transforms" a function that takes its arguments as a tuple, into a "chain" of functions that each takes 1 of the arguments. This is specifically handy when we want to compose a series of functions where some of them have been partially applied with arguments. See how the type of foo is changed:
- curry foo;
val it = fn : int -> int -> int
Now we can try and compose the two functions:
- (curry foo 5 o bar 1) 4;
val it = 130 : int
First 4 is applied to bar 1 as the argument x, then the result of that computation (bar 1 4) is given as the x argument to foo.
Obviously uncurry is used for the reverse process:
- uncurry bar;
val it = fn : int * int -> int