File: iterators.ml

package info (click to toggle)
js-of-ocaml 6.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 37,932 kB
  • sloc: ml: 135,957; javascript: 58,364; ansic: 437; makefile: 422; sh: 12; perl: 4
file content (74 lines) | stat: -rw-r--r-- 1,990 bytes parent folder | download | duplicates (3)
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
(* TEST *)

open Printf
open Effect
open Effect.Deep

(** {1 Iterators and generators} *)

(** Naive primality test. *)

let isprime n =
  let rec try_divide i =
    if i * i > n then true else
    if n mod i = 0 then false else
    try_divide (i + 2) in
  n mod 2 <> 0 && try_divide 3

(** Iterate [f] over all primes. *)

let iter_primes (f: int -> unit) : unit =
  for n = 2 to max_int do
    if isprime n then f n
  done

(** Produce the sequence of all primes. *)

let seq_primes : int Seq.t =
  let rec gen n : int Seq.t =
    if isprime n then (fun () -> Seq.Cons(n, gen (n + 1))) else gen (n + 1)
  in gen 2

(** Implementing [gen_primes] from [iter_prime], using control inversion. *)

type _ eff += Next_prime : int -> unit eff

let gen_primes : int Seq.t =
  match iter_primes (fun n -> perform (Next_prime n)) with
  | () -> Seq.empty
  | effect Next_prime n, k -> fun () -> Seq.Cons(n, continue k ())

let same_sequences (s1: 'a Seq.t) (s2: 'a Seq.t) =
  Seq.for_all2 (=) s1 s2

let _ =
  assert (same_sequences (Seq.take 100 seq_primes) (Seq.take 100 gen_primes))

(** More general transformation from iterator to sequence. *)

let iterator_to_sequence
       (type elt) (type collection)
       (iter: (elt -> unit) -> collection -> unit) : collection -> elt Seq.t =
  let module I2S = struct
    type _ eff += Next : elt -> unit eff
    let gen coll =
      match iter (fun elt -> perform (Next elt)) coll with
      | () -> Seq.empty
      | effect Next elt, k -> fun () -> Seq.Cons(elt, continue k ())
  end in I2S.gen

(** Application: the "same fringe" problem. *)

let same_fringe
    (iter1: ('elt -> unit) -> 'coll1 -> unit)
    (iter2: ('elt -> unit) -> 'coll2 -> unit)
    coll1 coll2 =
  same_sequences (iterator_to_sequence iter1 coll1)
                 (iterator_to_sequence iter2 coll2)

module IntSet = Set.Make(Int)

let _ =
  assert (same_fringe List.iter IntSet.iter
              [1; 2; 3]
              (IntSet.add 2 (IntSet.add 1 (IntSet.singleton 3))))