I want to find the Powerset
powerset [1;2;3] = = [[]; [3]; [2]; [2; 3]; [1]; [1; 3]; [1; 2]; [1;
2; 3]]
let rec powerset = function
| [] -> []
| x::xs -> List.map (fun ys -> xs) xs::powerset (xs)
I am having trouble with the code, this is what my output looks like now.
val it : int list list list = [[[2; 3]; [2; 3]]; [[3]]; []]
Others already pointed out to a link that uses sequence expressions and enumerates the sets lazily. That's how I would solve the problem (note that there is nothing impure or non-functional about using for inside sequence comprehension - it is just a way to generate sequence of results):
let rec powerset s = seq {
match s with
| [] -> yield []
| h::t -> for x in powerset t do yield! [x; h::x] }
That said, this can be easily translated to code that returns a list and uses higher-order functions:
let rec powerset =
function
| [] -> [[]]
| x::xs -> List.collect (fun subset -> [subset; x::subset]) (powerset xs)
The power set of an empty set is a set with single element [] (note that this is wrong in your snippet). To generate a powerset of x::xs, we first generate powerset of xs and then return two sets for every single element of the generated powerset - one is the sub set and the other is the subset with added x element. (This is done using List.collect which is like calling List.map followed by List.concat.)
Related
I'm creating a function that reverse a list.
I think all is good but the compiler isn't of the same opinion...
This is the code :
let reverse list_ =
let rec support list_ =
match list_ with
| [] -> []
| hd :: tl -> support tl :: hd in
let return = support list_ in return
The error is :
| hd :: tl -> support tl :: hd in
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list`
My idea is to reach the end of the list than I'll build a new list from [] adding the latest elements.
The operator :: is not symmetric. It takes a list element at the left and a list at the right. In this expression:
support tl :: hd
You have a list at the left (the result of the recursive call) and a list element at the right. So that's not going to work.
The error is telling you that support tl has type 'a list while the :: operator works like this: 1 :: [2;3] = [1;2;3]. Conceptually what you are trying to do is [3; 2] :: 1, which is not how the operator works.
If you want to append hd at the end of a list you need to use the # operator (or the append function):
let reverse list_ =
let rec support list_ =
match list_ with
| [] -> []
| hd :: tl -> support tl # [hd] in
let return = support list_ in return
Now the problem is time complexity, we are iterating through the entire list for each element. To deal with this we can use a list on which we accumulate the elements:
let reverse list =
let rec support acc list_ =
match list_ with
| [] -> acc
| hd :: tl -> support (hd :: acc) tl in
let return = support [] list in return
This code could be rewritten a bit considering that:
the expression let return = support [] list in return is the same as support [] list
let some_fun some_val = match some_val with (* ... *) can be written as let some_fun = function (* ... *) omitting some_val entirely
let reverse list =
let rec support acc = function
| [] -> acc
| hd :: tl -> support (hd :: acc) tl in
support [] list
I guess that using match or function is just a matter of personal preference though.
I implemented it using continuation. I think this is tail recursive but I'm told it's not. Why isn't it tail recursive?
let rec zip_tr fc sc l1 l2 = match l1, l2 with
| [], [] -> sc []
| [], _ -> fc (List.length l2)
| _, [] -> fc (List.length l1)
| h1::t1, h2::t2 ->
zip_tr fc (fun l -> sc ((h1, h2) :: l)) t1 t2
Isn't this tail recursive? Do the failure/success continuations have an effect effect on tail recursiveness?
There's only one recursive call in your code, and it is in tail position. So I would say your function is tail recursive.
It does build up a fairly large computation in the sc argument. However, the call to sc is in tail position also. In my tests, the function works for very large lists without running out of stack space.
If I try your function on two copies of a very long list (100,000,000 elements), it terminates successfully (after quite a long time). This suggests to me that it really is tail recursive.
Here is the session with the long list:
# let rec zip_tr fc sc l1 l2 = . . . ;;
val zip_tr :
(int -> 'a) -> (('b * 'c) list -> 'a) -> 'b list ->
'c list -> 'a = <fun>
# let rec mklong accum k =
if k <= 0 then accum
else mklong (k :: accum) (k - 1);;
val mklong : int list -> int -> int list = <fun>
# let long = mklong [] 100_000_000;;
val long : int list =
[1; 2; 3; 4; 5; ...]
# let long_pairs =
zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) long long;;
val long_pairs : (int * int) list =
[(1, 1); (2, 2); (3, 3); (4, 4); (5, 5); ...]
# List.length long_pairs;;
- : int = 100000000
If you change your code so that the call to sc is not a tail call:
zip_tr fc (fun l -> (h1, h2): sc l) t1 t2
It generates the result in reverse order, but it also fails for long lists:
# zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) [1;2] [3;4];;
- : (int * int) list = [(2, 4); (1, 3)]
# zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) long long;;
Stack overflow during evaluation (looping recursion?).
I'm don't know enough about OCaml code generation to explain this in detail, but it does suggest that your code really is tail recursive. However it's possible this depends on the implementation of closures. For a different implementation, perhaps the generated compuation for sc would consume a large amount of stack. Maybe this is what you're being told.
Using a tail-recursive function, you build something which is like a linked-list of continuations, by wrapping each sc inside another anonymous function; then, you call the resulting continuation.
Fortunately, your continuations are also tail-recursive, since the result of one call to sc directly gives the result of the anonymous closure. That explains why you don't have stack overflows when testing it.
The possible drawback of this function is that it allocates a lot of closures (but still with linear complexity) before starting to do any actual work, which is not what is usually done.
An advantage of this approach is that the success continuation is only called when both your lists are known to have the same size; more generally, compiling code to continuations is something that is interesting to know when working with languages (so your effort is not wasted).
If the function is part of some course, you are probably expected to directly build the result list while traversing your input lists, in a tail-recursive way, without delaying the work in continuations.
In OCaml, a typical fold function looks like this:
let rec fold (combine: 'a -> 'b -> 'b) (base: 'b) (l: 'a list) : 'b =
begin match l with
| [] -> base
| x :: xs -> combine x (fold combine base xs)
end
For those familiar with OCaml (unlike me), it should be pretty straightforward what it's doing.
I'm writing a function that returns true when all items in the list satisfy the condition: if condition x is true for all x in some list l. However I'm implementing the function using a fold function and I'm stuck. Specifically I don't know what the list should return. I know that ideally the condition should be applied to every item in the list but I have no idea how the syntax should look. x && acc works but it fails a very simply test (shown below)
let test () : bool =
not (for_all (fun x -> x > 0) [1; 2; -5; -33; 2])
;; run_test "for_all: multiple elements; returns false" test
Here is my preliminary attempt. Any help is appreciated:
let for_all (pred: 'a -> bool) (l: 'a list) : bool =
fold (fun(x:'a)(acc: bool)-> _?_&&_?_ )false l
let rec fold (combine: 'a -> 'b -> 'b) (base: 'b) (l: 'a list) : 'b =
match l with
| [] -> base
| x::xs -> combine x (fold combine base xs)
let for_all (pred: 'a -> bool) (lst: 'a list) =
let combine x accum =
(pred x) && accum
in
fold combine true lst
Your combine function should not do x && base because elements of the list are not usually bool. You want your predicate function first evaluate the element to bool, then you "and" it with the accumulator.
There is no need for begin and end in fold. You can just pattern match with match <identifier> with.
There are two widespread types of fold: fold_left and fold_right. You're are using fold_right, which, basically, goes through the whole list and begins "combining" from the end of the list to the front. This is not tail-recursive.
fold_left, on the other hand goes from the front of the list and combines every element with the accumulator right away. This does not "eat up" your stack by a number of recursive function calls.
I have this quite simple function which takes an int and adds it to the head of the list and is recursively called with i multiplied with itself:
let rec f i = function
| [] -> []
| x::xs -> (x+i)::f (i*i) xs
f 2 [1;2;3]
val it : int list = [3; 6; 19]
Now, I'm attempting to rewrite it using a continuation, but I'm a little stuck. Here's what I've come up with so far:
let fC i l =
let rec loop cont = function
| [] -> []
| x::xs -> cont(x+i)::loop (fun acc -> (acc*acc)) xs
loop id l
fC 2 [1;2;3] //Expected [3;6;19]
val it : int list = [3; 16; 25]
Any hints to what I'm doing wrong?
Looking at this questions and the comments it seems to me that there is some confusion.
Tail recursive does not necessary mean continuation passing style (CPS).
Here's the function in CPS:
let f' i p =
let rec loop i p k =
match p with
| [] -> k []
| x::xs -> loop (i*i) xs (fun a -> k ((x+i)::a))
loop i p id
And of course, it's tail recursive. But you can also write it tail recursive by using an accumulator instead of a continuation:
let f'' i p =
let rec loop i p acc =
match p with
| [] -> acc
| x::xs -> loop (i*i) xs ((x+i)::acc)
loop i p [] |> List.rev
See also the answer to this question to understand better CPS.
I am trying to get first and last element of the list in OCaml. I expect that my function will be like
'a list -> 'a * 'a
What I am trying to do is
let lista = [1;2;3;4;6;0];;
let rec first_last myList =
match myList with
[x] -> (List.hd lista,x)
| head::tail ->
first_last tail;;
first_last lista;;
Of course because of I made list as integer then I am doing this syntax like
*int list -> int * 'a
The point is that I dont have idea how to do this function for 'a.
Whats the direction?
The direction is to write two different functions first and last and implement the first_and_last function as:
let first_and_last xs = first xs, last xs
Another possibility with only one function:
let rec first_last = function
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You may prefer it like that:
let rec first_last myList = match myList with
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You can create two separate functions to return first element and last element, and then in your first_and_last function return a tuple (first_element, last_element).
let rec first_element list =
match list with
| [] -> failwith "List is empty"
| first_el::rest_of_list -> first_el
let rec last_element list =
match list with
| [] -> failwith "List is empty"
| [x] -> x
| first_el::rest_of_list -> last_element rest_of_list
You can create a helper function that has a base-case of the empty-list - for which it returns itself, and otherwise checks if the next recursive call will return an empty list. If it does, return the current element (which is by definition the last element in the list), and if it doesn't, return what was returned by the recursive call.
For the regular (non-helper) method, if the list is at least one element long (i.e. hd::tl = hd::[]) then you can just concatenate the list you got from the last function onto the head from ls.
It can be implemented as follow:
let rec last ls =
match ls with
| [] -> []
| hd::tl -> let next = last tl in
if next = [] then [hd]
else next
;;
let first_last ls =
match ls with
| [] -> failwith "Oh no!!!!! Empty list!"
| hd::tl -> hd::last tl
;;
Yet another take on this problem.
let first_last xs =
let rec last_non_empty = function
| [x] -> x
| _ :: xs' -> last_non_empty xs'
| [] -> failwith "first_last: impossible case!"
in
match xs with
| [] -> failwith "first_last"
| x::_ -> (x, last_non_empty xs)
Some properties of this implementation:
(1) it meets the specification 'a list -> 'a * 'a:
utop > #typeof "first_last";;
val first_last : 'a list -> 'a * 'a
(2) it works for singleton lists: first_last [x] = (x,x):
utop> first_last [1];;
- : int * int = (1, 1) utop> first_last ["str"];;
- : bytes * bytes = ("str", "str")
(3) it's tail-recursive (hence it won't cause stack overflow for sufficiently big lists):
utop > first_last (Array.to_list (Array.init 1000000 (fun x -> x+1)));;
- : int * int = (1, 1000000)
(4) it traverses the input list one time only; (5) it avoids creating new lists as it goes down the recursive ladder; (6) it avoids polluting the namespace (with the price of not allowing the reuse of a function like last).
And another rather simple variant, from the first principles (I was trying to illustrate "wishful thinking" in the spirit of the SICP book):
(* Not tail-recursive, might result in stack overflow *)
let rec first_last = function
| [] -> failwith "first_last"
| [x] -> (x,x)
| x :: xs -> (x, snd (first_last xs))
You could write it like this:
let first_last = function
| [] -> assert false
| x :: xs -> (x, List.fold_left (fun _ y -> y) x xs)
Or, if you are using the Base library, you could write in this way:
let first_last xs = (List.hd_exn xs, List.reduce_exn ~f:(fun _ y -> y) xs)
The basic idea is that List.fold_left (fun _ y -> y) x xs will compute the last element of x :: xs. You can prove this by induction on xs: if xs = [] then List.fold_left (fun _ y -> y) x [] = x, which is the last element of x :: []; moreover, if xs = x' :: xs' then List.fold_left (fun _ y -> y) x (x' :: xs') can be rewritten as List.fold_left (fun _ y -> y) x' xs', because List.fold_left f acc (x :: xs) = List.fold_left (f acc x) xs, hence we are finished, because this is the last element of x' :: xs' by our induction hypothesis.