summaryrefslogtreecommitdiff
path: root/src/nbc/sequence.sml
diff options
context:
space:
mode:
Diffstat (limited to 'src/nbc/sequence.sml')
-rw-r--r--src/nbc/sequence.sml74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/nbc/sequence.sml b/src/nbc/sequence.sml
new file mode 100644
index 0000000..73a3fbf
--- /dev/null
+++ b/src/nbc/sequence.sml
@@ -0,0 +1,74 @@
+signature SEQUENCE = sig
+ type 'a t
+ val fold: ('a * 'b -> 'b) -> 'b -> 'a t -> 'b
+ val from: (unit -> 'a option) -> 'a t
+ val map: ('a -> 'b) -> 'a t -> 'b t
+ val app: ('a -> unit) -> 'a t -> unit
+ val fromArray: 'a array -> 'a t
+ val fromList: 'a list -> 'a t
+ val toList: 'a t -> 'a list
+ val toArray: 'a t -> 'a array
+end
+
+structure Sequence :> SEQUENCE = struct
+ type 'a t = unit -> 'a option
+ fun fold f seed t =
+ let
+ fun loop x =
+ case t () of
+ NONE => x
+ | SOME y => loop (f (y, x))
+ in
+ loop seed
+ end
+ fun from t = t
+ fun map f t =
+ fn () => (
+ case t () of
+ NONE => NONE
+ | SOME x => SOME (f x)
+ )
+ fun app f t =
+ let
+ fun loop () =
+ case t () of
+ NONE => ()
+ | SOME x => (
+ f x
+ ; loop ()
+ )
+ in
+ loop ()
+ end
+ fun fromArray a =
+ let
+ val i = ref 0
+ fun f () =
+ if !i >= Array.length a then NONE
+ else
+ SOME (Array.sub (a, !i))
+ before i := !i + 1
+ in
+ from f
+ end
+ fun fromList l =
+ let
+ val c = ref l
+ fun f () =
+ case !c of
+ x :: y => (c := y; SOME x)
+ | nil => NONE
+ in
+ from f
+ end
+ fun toList t =
+ let
+ fun loop l =
+ case t () of
+ NONE => rev l
+ | SOME x => loop (x :: l)
+ in
+ loop nil
+ end
+ fun toArray t = Array.fromList (toList t)
+end