Implementing powerset function in ML using only map and folds - recursion

I need to implement a powerset function in ML that takes a list of ints with the following contraints:
1) Never call built in library functions except map, foldr, and foldl.
2) Never be recursive. All recursion occur within map and fold
3) Never contain let or local expressions
I've already implemented the function without these constraints using normal recursion of the form:
Powerset(x::xs) = powerset(xs) # x.powerset(xs)
I'm having trouble thinking of a way to translate this type of implementation into one that uses only maps and folds.
I'm not necessarily asking for someone to implement it for me, but I would appreciate a nudge in the right direction or any help for that matter.
Thakns

Here's how I go about solving problems with folds.
Think about the final value you want to obtain. In your case, this would be the powerset of the input list. The crucial question is now this: can the powerset of a list be recomputed after inserting a new element? That is, given P(S), the powerset of some set of items S, it is possible to compute P(S ∪ {x}) in terms of only P(S) and x?
I believe you've already answered this question definitively above. Not explicitly, perhaps, but if you rework your Powerset function, you'll find that the right idea is hidden in it. You'll want to package up this code into a little helper function:
fun extendPowerset (PS : 'a list list, x : 'a) : 'a list list =
(* PS is the powerset of some set S. This function
* should return the powerset of S ∪ {x}. *)
...
Great, now how do you plug that into a fold? Well, at each step of the fold, you are given two things:
the next element of the list, and
some value computed from all previous elements (think of this as a "summary" of the previous elements)
In return, you must compute a slightly larger summary: it should summarize the next element in addition to all previous. Doesn't this feel vaguely similar? The extendPowerset function is basically doing exactly what you need, where the "summary" of the previous elements is the powerset of those elements. I'll leave the rest to you.
Aside: note that you can also append two lists with a fold. As a hint, try working out what value is computed by foldl op:: [1,2] [3,4]. It's not quite like appending [1,2] and [3,4], but it's close...

Like you have already done, I would also first write a powerset function using explicit recursion. I would then try and discover the higher-order functional patterns and substitute those afterwards, one pattern at a time.
You might for example turn a helper function
fun consMany (x, []) = []
| consMany (x, L::Ls) = (x::L) :: consMany (x, Ls)
into the expression
map (fn L => x::L) Ls
You might eliminate a let-expression (useful for re-using a once-computed value twice)
fun foo (x::xs) =
let val rest = foo xs
in ... x ... rest ... rest ...
end
using a function:
fun foo (x::xs) =
bar (x, foo xs)
and bar (x, rest) = ... x ... rest ... rest ...
although, this might as well be an anonymous function:
fun foo (x::xs) =
(fn rest => ... x ... rest ... rest ...) (foo xs)
And you might turn a list-recursive function
fun derp [] = ...
| derp (x::xs) = g (x, derp xs)
into the fold:
fun derp xs = foldr g (...) xs
but if the order of your results don't matter, foldl is tail-recursive.

Related

How do I create a function which reverses an int list in OCaml?

I have a type intlist:
type intlist = Nil | Cons of int * intlist
and I'd now like to write a function that reverses the list. I have no real idea how to go about this. in class, our prof defined a function within a function, I believe, but I don't have the solution with me. How would one do this, simply? I would appreciate if we can keep the coding rather rudimentary, seeing as I'm relatively new to this.
So far, I only have
let reverse (l : intlist) : intlist =
match l with
Nil -> Nil
| Cons(a, Nil) -> Cons(a, Nil)
This is how I tend to create these kinds of functions, so I've written the trivial part (which granted, may not actually be what I need to start with). Any help is appreciated, thanks!
You indeed need a helper function, since for the reversing you need to build another list, so you need a function that will recurse into one list, while building another list, i.e., that has two arguments. In fact, this helper function is called rev_append and it is appending a reversed contents of one list to another. But let's try to make it using a helper function defined in the scope of the rev function:
let rev xs =
let rec loop xs ys = match xs with
| Nil -> ys
| Cons (x,xs) -> loop xs (Cons (x,ys)) in
loop xs Nil
So, to reverse a list we just take each element of a list and put it into another list. Since list behaves like a stack we are getting the reversed list for free. It is like Hanoi towers, when you pick elements from one list (tower) and put them to another, they will end up in a reversed order.

Function calling for each element in a list

Using only recursion (ie. no loops of any sort), given a list of elements, how can I call a function each time for every element of the list using that element as an argument each time in OCaml? Fold and map would not work because although they are applying a function to each element, it returns a list of whatever function I called on each element, which is not what I want.
To better illustrate what I'm essentially trying to do in OCaml, here's the idea of what I want in Ruby code:
arr.each {|x| some_function x}
but I must do this using only recursion and no iter functions
The correct recursive function is described as:
if the list is empty, do nothing;
else, process the first element and then the tail of the list.
The corresponding code is:
let rec do_all f lst =
match lst with
| [] -> ()
| x :: xs -> f x; do_all f xs
A fairly general template for a recursive function would be this:
let rec f x =
if x is trival to handle then
handle x
else
let (part, rest) = division of x into smaller parts in
let part_result = handle_part part in
let recursive_result = f rest in
combine part_result recursive_result
Since you don't need a result, you can skip a lot of this.
Which parts of this template seem most difficult to do for your problem?
Update
(As #EduardoLeón points out, when working with lists you can test for a trivial list and break down the list into smaller parts using pattern matching. Pattern matching is cool.)
Update 2
My question is sincere. Which part are you having trouble with? Otherwise we don't know what to suggest.

Curried Functions in Standard ML

I've been banging my head against the wall trying to learn about curried functions. Here's what I understand so far; suppose I have a function:
fun curry (a b c) = a * b * c;
or
fun curry a b c = a * b * c;
In ML, I can only have one argument so the first function uses a 3-tuple to get around this / get access to a, b, and c.
In the second example, what I really have is:
fun ((curry a) b) c
where curry a returns a function, and
(curry a) b returns a function and ((curry a) b) c returns another function. A few questions:
1) Why is this preferable to using a tuple? Is it just that I can make use of the intermediate functions curry a and (curry a) b. My book mentions partial instantiation but not totally clear on it.
2) How do you determine what function curry a, (curry a) b actually do? ((curry a) b) c is just a * b * c, right?
Thanks for any help clearing this up,
bclayman
There is an element of taste in using curried vs. non-curried functions. I don't use curried functions as a matter of course. For example, if were to write a gcd function I would tend to write it as a function designed to operated on a tuple simply because I seldom have use for a defined partially-instantiated gcd function.
Where curried functions are really useful is in defining higher-order functions. Consider map. It is easy enough to write a non-curried version:
fun mymap (f,[])= []
| mymap (f,x::xs) = f(x)::mymap(f,xs)
It has type fn : ('a -> 'b) * 'a list -> 'b list taking a tuple consisting of a function between two types and a list of elements of the input type, returning a list of element of the output type. There is nothing exactly wrong with this function, but -- it isn't the same as SML's map. The built-in map has type
fn : ('a -> 'b) -> 'a list -> 'b list
which is curried. What does the curried function do for us? For one thing, it can be thought of as a function transformer. You feed map a function, f, designed to operate on elements of a given type and it returns as function map f which is designed to operate on whole lists of elements. For example, if
fun square(x) = x*x;
Is a function designed to square ints then val list_square = map square defines list_square as a function which takes a list of elements and returns the list of their squares.
When you use map in a call like map square [1,2,3] you have to remember that function application is left associative so that this parses as
'(map square) [1,2,3]. The functionmap square*is* the same as the functionlist_squareI defined above. The invocationmap square [1,2,3]takes that function and applies it to[1,2,3]yielding[1,4,9]`.
The curried version is really nice if you want to define a function, metamap, which can be used to apply functions to each element of a matrix thought of as a list of lists. Using the curried version it is as simple as:
fun metamap f = map (map f)
used like (in the REPL):
- metamap square [[1,2],[3,4]];
val it = [[1,4],[9,16]] : int list list
The logic is that map lifts a function from applying to elements to applying to lists. If you want a function to apply to lists of lists (e.g. matrices) just apply map twice -- which is all metamap does. You could, of course, write a version a non-curried version of metamap using our noncurried mymap function (it wouldn't even be all that hard), but you wouldn't be able to approach the elegance of the 1-line definition above.

Why did I still get stackoverflow even if I used tail-recursion in OCaml?

I wrote a function which generates a list of randomized ints in OCaml.
let create_shuffled_int_list n =
Random.self_init;
let rec create n' acc =
if n' = 0 then acc
else
create (n'-1) (acc # [Random.int (n/2)])
in
create n [];;
When I tried to generate 10000 integers, it gives Exception: RangeError: Maximum call stack size exceeded. error.
However, I believed in the function, I have used tail-recursion and it should not give stackoverflow error, right?
Any idea?
From the core library documentation
val append : 'a list -> 'a list -> 'a list
Catenate two lists. Same function as the infix operator #. Not tail-recursive (length of the first argument). The # operator is not tail-recursive either.
So it's not your function that's causing the overflow, it's the # function. Seeing as you only care about producing a shuffled list, however, there's no reason to be appending things onto the end of lists. Even if the # operator were tail-recursive, list append is still O(n). List prepending, however, is O(1). So if you stick your new random numbers on the front of your list, you avoid the overflow (and make your function much much faster):
let create_shuffled_int_list n =
Random.self_init;
let rec create n' acc =
if n' = 0 then acc
else
create (n'-1) (Random.int (n/2) :: acc)
in
create n [];;
If you care about the order (not sure why), then just stick a List.rev on the end:
List.rev (create n []);;
As an aside, you should not call Random.self_init in a function, since:
the user of your function may want to control the seed in order to obtain reproductible results (testing, sharing results...)
this may reset the seed with a not so random entropy source and you probably want to do this only once.

Using fold in SML

I'm trying to learn smlnj at the moment and am having trouble with a fold function.
What I'm trying to do is write a function, select, that uses the folding pattern and takes in a function and a list. It will take the head of the list into the function to determine whether it will add that element to the list. Here is an example of what I mean.
select (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
val it = [2,4,6,8,10] : int list
So, here is what I have so far...
fun select f l = foldl (fn (x,y) => if (f(x)) then x else 0) 0 l;
This obviously doesn't work correctly. It simply returns 10. I'm sure I need to use op:: somehow to get this to work, but I can't figure it out. My thought is that it should look something like this...
fun select f l = foldl (fn (x,y) => if (f(x)) then op:: else []) [] l;
But this does not work. Any help would be appreciated. Thanks!
You're close. The only problems are the if/else cases in the function you're passing to fold.
Remember, in your fn (x,y), x is the list element you're considering, and y is the result of folding the rest of the list. If f(x) fails, then you want to exclude x from the result, so you just pass y along. If f(x) succeeds, you want to include x in your result, so you return y#[x].
Note that it's best to avoid using the append operator (y#[x]) where you can, as it's a linear-time operation, while prepending (x::y) is constant. Of course, substituting one for the other in this case will construct your list backwards. You can get around this by folding backwards as well, i.e. using foldr instead of foldl.
What you're implementing already exists. It's called filter.
- List.filter (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
val it = [2,4,6,8,10] : int list
Your attempt in your second code sample is pretty close. There are several issues I might point out:
op:: is an operator, which is a function. You probably don't want to return a function. Instead, you probably want to use the operator to create a list from a head element and the rest of the list, like this: x :: y
In the else case, you are currently returning an empty list, and throwing away whatever was accumulated in y. You probably don't want to do that.
Think about whether left-fold or right-fold would be most suitable for your output

Resources