How to generate recursive list in OCaml - recursion

I would like to implement analog of Haskell cycle function.
If I pass list elements explicitly it seems trivial:
let cycle a b c =
let rec l = a::b::c::l in
l
cycle 1 2 3 generates recursive list 1, 2, 3, 1...
But, how to generate recursive list on basis of another regular list?
let cycle lst = ...
Usage
cycle [1;2;3]

In an eager language like ML, you need to use streams. For example
# let cycle = Stream.from (fun n -> Some (List.nth [1;2;3] (n mod 3)));;
val cycle : int Stream.t = <abstr>
# Stream.npeek 10 cycle;;
- : int list = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1]

As far as I can see, OCaml doesn't lend itself to this kind of coding unless you want to descend into the unsafe parts of the language.
Sticking to the safe parts of the language (but using extensions from Chapter 7), here is a (not very impressive) version of cycle that works for lists up to length 3:
let cycle = function
| [] -> []
| [x] -> let rec res = x :: res in res
| [x; y] -> let rec res = x :: q and q = y :: res in res
| [x; y; z] -> let rec res = x :: t and t = y :: v and v = z :: res in res
| _ -> failwith "list too long"
It's easy to see how to extend this to any desired fixed length, but not to arbitrary length.
Here's a session with the function:
# #use "cyc.ml";;
val cycle : 'a list -> 'a list = <fun>
# cycle [1;2;3];;
- : int list =
[1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1;
2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2;
3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3;
1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1;
2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2;
3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; ...]
This is the best I can do, at any rate. I hope it's helpful.

It seems the only way to make such recursive list is by using Obj module.
Copy the list and make it recursive
let cycle lst = match lst with
| [] -> []
| _ ->
let rec get_last_cell = function
| [] -> assert false
| _::[] as last -> last
| _::tl -> (get_last_cell tl)
in
let new_lst = List.map (fun x -> x) lst in
let last_cell = get_last_cell new_lst in
Obj.set_field (Obj.repr last_cell) 1 (Obj.repr new_lst);
new_lst
Create recursive list and then insert new cons cells
let cycle lst = match lst with
| [] -> []
| hd::tl ->
let rec loop cell lst =
match lst with
| [] -> ()
| hd::tl ->
let new_cell = [hd] in
let new_cell_obj = Obj.repr new_cell in
let cell_obj = Obj.repr cell in
Obj.set_field new_cell_obj 1 (Obj.field cell_obj 1);
Obj.set_field cell_obj 1 new_cell_obj;
loop new_cell tl
in
let rec cyc_lst = hd::cyc_lst in
loop cyc_lst tl;
cyc_lst
The idea is pretty straightforward:
Create recursive list cyc_lst with only one element.
Insert one or more new cons cells immediately before tail of cyc_lst.
Example
cycle [1;2]
Create recursive list cyc_lst. It is represented in memory as a self-recursive cons cell
let rec cyc_lst = hd::cyc_lst
.--------.
| |
| +---+-|-+
`->| 1 | * |
+---+---+
Create new_cell using 2 as the only element
let new_cell = [hd]
cell new_cell
.--------.
| |
| +---+-|-+ +---+---+
`->| 1 | * | | 2 | X |
+---+---+ +---+---+
Set new_cell tail pointer to first cell
Obj.set_field new_cell_obj 1 (Obj.field cell_obj 1)
cell new_cell
.--------.--------------.
| | |
| +---+-|-+ +---+-|-+
`->| 1 | * | | 2 | * |
+---+---+ +---+---+
Set cell tail pointer to new_cell
Obj.set_field cell_obj 1 new_cell_obj
cell new_cell
.-----------------------.
| |
| +---+---+ +---+-|-+
`->| 1 | *------->| 2 | * |
+---+---+ +---+---+
I hope GC is ok with such list manipulations. Let me know if it is not.

You can define it like so also
# let cycle items =
let buf = ref [] in
let rec next i =
if !buf = [] then buf := items;
match !buf with
| h :: t -> (buf := t; Some h)
| [] -> None in
Stream.from next;;
val cycle : 'a list -> 'a Stream.t = <fun>
utop # let test = cycle [1; 2; 3];;
val test : int Stream.t = <abstr>
utop # Stream.npeek 10 test;;
- : int list = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1]
This is from:
http://ocaml.org/tutorials/streams.html

You need streams as in another answer, or lazy lists:
type 'a llist = LNil | LCons of 'a * 'a llist Lazy.t
let cycle = function
| [] -> invalid_arg "cycle: empty list"
| hd::tl ->
let rec result =
LCons (hd, lazy (aux tl))
and aux = function
| [] -> result
| x::xs -> LCons (x, lazy (aux xs)) in
result

Related

Call lazy-list function in OCaml

How would I call the following function in order to compute the numbers from 1 to 100 e.g.?
type 'a llist = Cons of 'a * (unit -> 'a llist)
let rec lnat n = Cons (n, fun () -> lnat (n+1))
Calling lnat 1 gives me the following:
lnat 1;;
- : int llist = Cons (1, <fun>)
But how do I compute the following numbers?
If the goal is to convert a (finite prefix of an) llist to an ordinary list, we can do that with a simple recursive helper function.
let rec take n (Cons (x, xs)) =
if n = 0 then [] else x :: take (n - 1) (xs ())
Use as
# take 100 (lnat 1);;
- : int list =
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20; 21;
22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; 35; 36; 37; 38; 39; 40;
41; 42; 43; 44; 45; 46; 47; 48; 49; 50; 51; 52; 53; 54; 55; 56; 57; 58; 59;
60; 61; 62; 63; 64; 65; 66; 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78;
79; 80; 81; 82; 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97;
98; 99; 100]
The llist in your representation stores the first value strictly and then hides the rest of the computation behind a function that takes (). Since the function takes () (i.e. no real arguments), its only choice (aside from producing side effects, which I feel would be unexpected behavior in this context) is to produce a constant value.
So it really is just an infinite list, where the function part "protects" the rest of the list from flooding your computer's memory. To access the following element, apply the function to (), the only valid value of type unit.

How do I concatenate a vector of integers into a single integer?

I'm trying to concatenate all of the contents of a vector into a single number. This would be like [1, 2, 4] -> 124. Here's what I have right now:
fn sumVector(vec: &Vec<u32>) -> u32 {
return vec.to_owned().concat();
}
This is failing with error
error[E0599]: no method named `concat` found for type `std::vec::Vec<u32>` in the current scope
--> src/lib.rs:2:27
|
2 | return vec.to_owned().concat();
| ^^^^^^ method not found in `std::vec::Vec<u32>`
As said in the comments by Stargateur, you can do:
fn concat(vec: &[u32]) -> u32 {
vec.iter().fold(0, |acc, elem| acc * 10 + elem)
}
You can also write the same function in imperative style:
fn concat(vec: &[u32]) -> u32 {
let mut acc = 0;
for elem in vec {
acc *= 10;
acc += elem;
}
acc
}
You can follow Ortomala Lokni's procedure if your input vector contains single digit integers.
If the vector contains multi-digit integers, the function may not return the intended value. The following concat_new function handles this case.
fn main() {
let a = vec![10_i32, 20, 300];
println!("{:?}", concat_new(&a));
println!("{:?}", concat(&a));
}
fn concat_new(vec: &[i32]) -> i32 {
let t = vec.iter().fold("".to_string(), |acc, x| acc + &x.to_string());
t.parse::<i32>().unwrap()
}
fn concat(vec: &[i32]) -> i32 {
vec.iter().fold(0, |acc, elem| acc * 10 + elem)
}

F#: Attributes on discriminated union fields?

I can do this:
type AttrAttribute () =
inherit Attribute ()
type MyDU =
| [<Attr>]A of bool
| [<Attr>]B of int * string
| [<Attr>]C of byte * char * int64
... but is there any way to do this?
type MyDU =
| A of [<Attr>]bool
| B of int * [<Attr>]string
| C of [<Attr>]byte * char * [<Attr>]int64
Apparently, the case values are just fields (e.g. let v = B (13, "oops") in (Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields (v, v.GetType ()) |> fst).GetFields ()), so I'm hoping this is doable, somehow.
This is quite contrived:
type A_ = { [<Attr>] Item1 : int }
type B_ = { [<Attr>] Item1 : int; [<Attr>] Item2 : string }
type MyDU =
| A of A_
| B of B_
And
let v = A({Item1 = 1})
let record = ((FSharpValue.GetUnionFields (v, v.GetType ()) |> fst).GetFields ()) |> Array.head
let attrs = record.PropertyType.GetProperties() |> Array.collect(fun p -> p.GetCustomAttributes(false))

Recursively unpack list into elements

I have a list and would like to return each element from it individually. Basically like popping from a stack. For example:
let rnd = new System.Random()
let rnds = List.init 10 (fun _ -> rnd.Next(100))
List.iter (fun x -> printfn "%A"x ) rnds
However instead of iterating, I would actually like to return each integer one after the other until the list is empty. So basically something along the lines of:
List.head(rnds)
List.head(List.tail(rnds))
List.head(List.tail(List.tail(rnds)))
List.head(List.tail(List.tail(List.tail(List.tail(rnds)))))
Unfortunately my attempts at a recursive solution or even better something using fold or scan were unsuccessful. For example this just returns the list (same as map).
let pop3 (rnds:int list) =
let rec pop3' rnds acc =
match rnds with
| head :: tail -> List.tail(tail)
| [] -> acc
pop3' [] rnds
Would uncons do what you need?
let uncons = function h::t -> Some (h, t) | [] -> None
You can use it to 'pop' the head of a list:
> rnds |> uncons;;
val it : (int * int list) option =
Some (66, [17; 93; 33; 17; 21; 1; 49; 5; 96])
You can repeat this:
> rnds |> uncons |> Option.bind (snd >> uncons);;
val it : (int * int list) option = Some (17, [93; 33; 17; 21; 1; 49; 5; 96])
> rnds |> uncons |> Option.bind (snd >> uncons) |> Option.bind (snd >> uncons);;
val it : (int * int list) option = Some (93, [33; 17; 21; 1; 49; 5; 96])
This seems like a good oppurtunity for a class
type unpacker(l) =
let mutable li = l
member x.get() =
match li with
|h::t -> li<-t;h
|_ -> failwith "nothing left to return"

Find unique array of tuples

I have 4 arrays of different data. For the first array of string, I want to delete the duplicate element and get the results of array of unique tuples with 4 elements.
For example, let's say the arrays are:
let dupA1 = [| "A"; "B"; "C"; "D"; "A" |]
let dupA2 = [| 1; 2; 3; 4; 1 |]
let dupA3 = [| 1.0M; 2.0M; 3.0M; 4.0M; 1.0M |]
let dupA4 = [| 1L; 2L; 3L; 4L; 1L |]
I want the result to be:
let uniqueArray = [| ("A", 1, 1.0M, 1L); ("B", 2, 2.0M, 2L); ("C", 3, 3.0M, 3L); ("D",4, 4.0M, 4L) |]
You will first need to write a zip4 function which will zip the arrays:
// the function assumes the 4 arrays are of the same length
let zip4 a (b : _ []) (c : _ []) (d : _ []) =
Array.init (Array.length a) (fun i -> a.[i], b.[i], c.[i], d.[i])
Then a distinct function for arrays, using Seq.distinct:
let distinct s = Seq.distinct s |> Array.ofSeq
And the result would be:
> zip4 dupA1 dupA2 dupA3 dupA4 |> distinct;;
val it : (string * int * decimal * int64) [] =
[|("A", 1, 1.0M, 1L); ("B", 2, 2.0M, 2L); ("C", 3, 3.0M, 3L);
("D", 4, 4.0M, 4L)|]
let zip4 s1 s2 s3 s4 =
Seq.map2 (fun (a,b)(c,d) ->a,b,c,d) (Seq.zip s1 s2)(Seq.zip s3 s4)
let uniqueArray = zip4 dupA1 dupA2 dupA3 dupA4 |> Seq.distinct |> Seq.toArray

Resources