How can I use one of the fold functions to generate a list of integers from 0 to a value n-1? I'm confused about how to get fold_right to return a list rather than returning just an accumulated value.
This is for a helper function that I'm trying to define to solve a larger problem. Here is my attempt:
-I know the base case has to be a list containing only zero, because I do not want to add anything less than zero.
-I know that I need to decrement the value n so that I can put numbers from n-1 to 0 in the list.
let buildList n =
let ibuildList elem list =
list#[n-1]
in List.fold_right ibuildList n [0];;
But I get an error underscoring "n" in the last line saying that the expression has type int but an expression was expected of type 'a list. Isn't n an integer that I'm turning into a list via [n-1]? Where did I go wrong?
Very sorry, I missed at least one step of the reasoning.
A fold is for traversing a collection. Since you want to generate a list and you just have n, not a collection, you can't really use fold in any reasonable way. In fact, what you want to do is more like an unfold. I.e., you want to unfold your n into a list.
It's easy to write this function, but not easy to write it using a fold.
Here's an implementation of unfold in OCaml:
let rec unfold_right f init =
match f init with
| None -> []
| Some (x, next) -> x :: unfold_right f next
Here's how to use unfold_right to generate a list of ints:
let range n =
let irange x = if x > n then None else Some (x, x + 1) in
unfold_right irange 1
Here's how it looks when you run range:
# range 0;;
- : int list = []
# range 8;;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8]
# range 5;;
- : int list = [1; 2; 3; 4; 5]
An alternative version, using the standard Stream module:
(* an infinite stream of natural numbers, starting from 0 *)
let nats =
let rec nats_from n = [< 'n; nats_from (n + 1) >] (* extra syntax *)
in nats_from 0
(* the first n natural numbers: [0; n-1] *)
let range n = Stream.npeek n nats
The piece [< 'n; nats_from (n + 1) >] represents a lazy list with n as its head and the next natural numbers as its tail. Stream.npeek n stream consumes the first n elements of stream and returns them as a list.
Tests with utop:
utop # #load "dynlink.cma";; (* you need these to work with *)
utop # #load "camlp4o.cma";; (* the Stream's syntactic extension *)
utop # range 1;;
- : int list = [0]
utop # range 5;;
- : int list = [0; 1; 2; 3; 4]
utop # range 10;;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]
If you'd like to compile it, use the following commands (you need to use the camplp4o preprocessor):
$ ocamlc -pp camlp4o <filename>.ml
or
$ ocamlopt -pp camlp4o <filename>.ml
Related
I am trying to write a simple function in OCaml
let rec pell (i: int) =
(if i <= 2 then i (*if given n is less tahn 2 then return 2, else return previous n-1 th term and n-2 nd term recursively*)
else if i>2 then
2 * pell i - 1 + pell i - 2
else failwith "unimplemented" (*else fail with unimplemented message*)
);;
Write an infinite precision version of the pell function from before
pell2 0 = []
pell2 1 = [1]
pell2 7 = [9; 6; 1]
pell2 50 = [2; 2; 5; 3; 5; 1; 4; 2; 9; 2; 4; 6; 2; 5; 7; 6; 6; 8; 4]
I have written below code for this:
let rec pell2 i =
(if i <= 2 then
[] -> i;
else if i=0 then [];
else if i>2 then (*finding pell number and using sum function to
output list with infinite precision...*)
[] -> pell2 i-1 + pell2 i-2;
else failwith "unimplemented"
);;
but still has some syntax errors. Can someone help me with this please.
if i <= 2 then
[] -> i
In snippets like this, the -> is invalid. It looks like you might be mixing pattern matching with match ... with ... and if/else up.
Also, you're first checking if i is less than or equal to 2, but then you have an else to test for i being equal to zero. The first check means the second is never going to happen.
First, let's look at the examples for the output of pell2. We see that pell2 has a single integer parameter, and returns a list of integers. So, we know that the function we want to create has the following type signature:
pell2: int -> int list
Fixing (some but not all of) the syntax errors and trying to maintain your logic,
let rec pell2 i =
if i=0 then []
else if i <= 2 then i
else if i>2 then pell2 i-1 + pell2 i-2
Note that I removed the semicolons at the end of each expression since OCaml's use of a semicolon in its syntax is specifically for dealing with expressions that evaluate to unit (). See ivg's excellent explanation on this. The major flaw with this code is that it does not type check. We see that we conditionally return a list, and otherwise return an int. Notice how above we defined that pell2 should return an int list. So, we can begin fixing this by wrapping our int results in a list:
let rec pell2 n =
if n = 0 then []
else if n <= 2 then [n]
else ... something that will return the Pell number as a list ...
As you have already written, the else branch can be written using recursive calls to the pell2 function. However, we can't write it as you did previously, because pell2 evaluates to a list, and the binary operator + only works on two integers. So, we will have to define our own way of summing lists. Calling this sum_lists, we are left with the following code:
We can now fully define our function pell2:
let rec pell2 n =
if n = 0 then []
else if n <= 2 then [n]
else (* Pell(n) = (2 * Pell(n-1)) + Pell(n-2) *)
let half_of_first_term = pell2 n-1 in
let first_term = sum_lists half_of_first_term half_of_first_term in
let second_term = pell2 n-2 in
sum_lists first_term second_term
So, all that is left is to define sum_lists, so that we are properly summing together two lists of the same format as the return type of pell2. The signature for sum_lists would be
sum_lists: int list -> int list -> int list
I'll give a basic outline of the implementation, but will leave the rest for you to figure out, as this is the main crux of the assignment problem.
let sum_lists lst1 lst2 =
let rec sum_lists_helper lst1 lst2 carry =
match lst1, lst2 with
| [], [] -> if carry = 1 then [1] else []
| h::t, []
| [], h::t -> ...
| h1::t1, h2::t2 -> ...
in
sum_lists_helper lst1 lst2 0
let rec slice l i k = match l with
h::t -> if (k == 0) then h
else if (i == 0) then h # (slice t 0 (k-1))
else slice t (i-1) (k-1);;
When I enter slice [1; 2; 3; 4] 1 2;; I get:
Error: This expression has type int but an expression was expected of type 'a list
however if I enter slice [[1]; [2]; [3]; [4]] 1 2;; it works as intended. I don't understand why OCaml thinks l is a list of lists of 'a, and not just a standard list of 'a?
I see two problems. In your first case you return h. But you should be returning a list, and h is the first element of your list.
In your second case you use the # operator, which expects a list on both sides. But h is the first element of your list, not a list. You can fix this by using :: instead of #.
Other problems:
I don't see a place where you handle an empty list l.
You should use = rather than ==. The == operator in OCaml is for very special purposes only. For day-to-day equality comparisons you want to use =.
I have a function:
let rec multiply x ls =
match ls with
[] -> []
| h::tl -> (x * h) :: multiply x tl
multiply 2 [1;2;3] = [2;4;6]
I would like a function that calls multiply from n to 0. I keep having problems because of the base case:
let rec multiply_all x ls = if x > 0
then (multiply n ls) :: multiply_all (n-1) (ls) else ????
I am not sure what to put after the else. I tried to make it
if x > 1 then (multiply n ls) :: multiply_all (n-1) (ls) else multiply all 1.
but that doesn't work.
Putting 1 there certainly doesn't work since multiply_all must return a list. So you need a list (of lists of int) to put there. But which list should it be?
The short answer is that in such simple cases, the list you need is usually the empty list: [].
As a slightly longer answer, we can consider the case for multiply_all 0 in relation to the intended results of multiply_all 1, multiply_all 2, etc., and try to find a pattern that fits. We want multiply_all to behave like this:
# multiply_all 2 [1;2;3];;
- : int list list = [[2; 4; 6]; [1; 2; 3]]
# multiply_all 1 [1;2;3];;
- : int list list = [[1; 2; 3]]
So calling multiply_all with some number N as first argument should give us a list of length N. In particular, multiply_all with N = 0 should give a list of length 0. The list of length 0 is the empty list.
Here is your completed definition:
let rec multiply_all x ls =
if x > 0 then (multiply x ls) :: multiply_all (x-1) (ls) else []
Just an other solution :
let multiply_all n l =
let multiply n= List.map (( * ) n) in
let rec aux i acc =
if i > n then acc
else aux (i+1) (multiply i l :: acc)
in
aux 1 []
;;
Test :
# multiply_all 5 [1;2;3];;
- : int list list =
[[5; 10; 15]; [4; 8; 12]; [3; 6; 9]; [2; 4; 6]; [1; 2; 3]]
First of all, your multiply method is pretty inefficient since it isn't tail recursive. Furthermore, the standard library provides you with tools to make that kind of function easier to write:
let multiply n = List.map (( * ) n);;;
val multiply : int -> int list -> int list = <fun>
multiply 5 [1;2;3];;
- : int list = [5; 10; 15]
Note: Also, use partial application when it doesn't obfuscate your code.
As of multiply_all, I'm not sure how to achieve it without JaneStreet's Core (see this question). However, here is a possible implementation using Core:
open Core.Std;; (*Using Core*)
let multiply_all n l =
let multiples = List.init n ~f:(fun x -> n-x) in (*This doesn't exist in Pervasives*)
List.map multiples ~f:(fun m -> multiply l m);;
val multiply_all : int list -> int -> int list list = <fun>
multiply_all 5 [1;2;3];;
- : int list list = [[5; 10; 15]; [4; 8; 12]; [3; 6; 9]; [2; 4; 6]; [1; 2; 3]]
Hope it helps. I'll keep this answer updated with my findings about List.init.
I am trying to implement the following program in Ocaml:
Write a shuffle : α list → α list → α list procedure, which will return a list with elements from 2 lists shuffled according to the following rules:
all of the lists from 2 input lists are on the output lists
elements from both lists are in the same order as previously
elements of at least one the input lists are not next to each other on the output list
Example outputs of shuffle [5; 7; 0; 5] [3; 2; 8; 9; 3]:
[5; 3; 2; 7; 8; 9; 0; 3; 5]
[3; 5; 2; 7; 8; 0; 9; 5; 3]
I know how to implement a simple shuffle function (taken from here):
let shuffle d =
let nd = List.map (fun c -> (Random.bits (), c)) d in
let sond = List.sort compare nd in
List.map snd sond
Can you please give me any tips on how should I go from there?
Here's a simple random interspersal that meets the first two requirements:
let shuffle a b =
let rec loop a b = match a, b with
| [], r
| r, [] -> r
| x::xs, y::ys ->
if Random.bool () then x::loop xs b
else y::loop a ys in
loop a b
See if you can adapt the way it selects which list to take an element from to also meet the third requirement. You might want to collect some information about the lists before starting that you can feed into the decision.
I want to write a function that does builds a list between two ints, inclusive
rec myFunc x y would build a list with all the ints between x and y, including x and y
For the logic right now I have something like this:
let rec buildList i n = let x = i+1 in if i <= n then i::(buildList x n)
But this gives me an error "Expression has type 'a list but but an expression was expected of type unit.
I thought buildList is returning a list of ints, and i as an int, so the cons operator would be valid, but its saying it should be void?
Why does this happen, and how do I fix it?
If the condition is true, you return the list i::(buildList x n). If it's not true, what do you return ?
Add else [] to your function to return the empty list when the condition is not met.
When you don't have any else, the compiler supposes it is else () (hence the error message).
Your if is missing an else condition
I suggest that you use a tail recursive function:
let buildList x y =
let (x,y) = if x<y then (x,y) else (y,x) in
let rec aux cpt acc =
if cpt < x then acc
else aux (cpt-1) (cpt::acc)
in aux y []
First, make sure that you ordered your boundaries correctly (idiot-proof), and then construct the list thank to a local recursive function which takes an accumulator.
Two alternatives relying on batteries' package,
Using unfold, which purpose is to build list,
let range ~from:f ~until:u =
BatList.unfold f (function | n when n <= u -> Some (n, succ n) | _ -> None)
Using Enum, allowing to work with lazy datastructure,
# BatList.of_enum ## BatEnum.(1--9);;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9]
My suggestion, this respects the ordering of the arguments.
let rec iota n m =
let oper = if n < m then succ else pred in
if n = m then [n] else n :: iota (oper n) m
Edit:
The operator selection is inside the recursive part, it should better be outside like this:
let iota n m =
let oper = if n < m then succ else pred in
let rec f1 n m = if n = m then [n] else n :: f1 (oper n) m in
f1 n m
At more than 200000 elements I get a stack overflow (so here we are)
# iota 0 250000;;
Stack overflow during evaluation (looping recursion?).
Todo: tail recursion
let buildList i n =
let rec aux acc i =
if i <= n then
aux (i::acc) (i+1)
else (List.rev acc)
in
aux [] i
Test:
# buildList 1 3;;
- : int list = [1; 2; 3]
# buildList 2 1;;
- : int list = []
# buildList 0 250000;;
- : int list =
[0; 1; 2; 3; .... 296; 297; 298; ...]