[MLton-commit] r5038
Vesa Karvonen
vesak at mlton.org
Fri Jan 12 04:29:32 PST 2007
Initial commit of a lib of misc utils to be refactored.
----------------------------------------------------------------------
A mltonlib/trunk/com/ssh/misc-util/unstable/node.sml
----------------------------------------------------------------------
Added: mltonlib/trunk/com/ssh/misc-util/unstable/node.sml
===================================================================
--- mltonlib/trunk/com/ssh/misc-util/unstable/node.sml 2007-01-12 12:29:12 UTC (rev 5037)
+++ mltonlib/trunk/com/ssh/misc-util/unstable/node.sml 2007-01-12 12:29:27 UTC (rev 5038)
@@ -0,0 +1,159 @@
+(* Copyright (C) 2007 SSH Communications Security, Helsinki, Finland
+ *
+ * This code is released under the MLton license, a BSD-style license.
+ * See the LICENSE file or http://mlton.org/License for details.
+ *)
+
+(*
+ * Imperative singly linked list node. This is useful and often more
+ * convenient than a functional list when implementing imperative data
+ * structures.
+ *
+ * Note that imperative lists may form cycles and, unless otherwise
+ * specified, procedures specified in this module are not specifically
+ * designed to work with cyclic lists.
+ *)
+
+structure Node :> sig
+ eqtype 'a t
+
+ val new : 'a t Thunk.t
+ (** Allocates a new empty node. *)
+
+ val get : 'a t -> ('a * 'a t) Option.t
+ (** Returns the contents of the node. *)
+
+ val <- : ('a t * ('a * 'a t) Option.t) Effect.t
+ (** Sets the contents of the node. *)
+
+ val isEmpty : 'a t UnPr.t
+ (** Returns true iff the imperative list is empty. *)
+
+ val hd : 'a t -> 'a
+ (**
+ * Returns the first element of the imperative list. Raises {Empty} if
+ * the list is empty.
+ *)
+
+ val tl : 'a t -> 'a t
+ (**
+ * Returns the next node of the imperative list. Raises {Empty} if the
+ * list is empty.
+ *)
+
+ val push : 'a t -> 'a Effect.t
+ (**
+ * Inserts the given element into the imperative list after the given
+ * node.
+ *)
+
+ val take : 'a t -> 'a Option.t
+ (**
+ * If the imperative list is non-empty, removes the first element {v}
+ * of the list and returns {SOME v}. Otherwise returns {NONE}.
+ *)
+
+ val drop : 'a t Effect.t
+ (**
+ * If the imperative list is non-empty, removes the first element of
+ * the list. Otherwise does nothing.
+ *)
+
+ val clearWith : 'a Effect.t -> 'a t Effect.t
+ (**
+ * Takes all elements of the imperative list of nodes one-by-one and
+ * performs the given effect on the removed elements.
+ *)
+
+ val fromList : 'a List.t -> 'a t
+ (** Constructs an imperative list from a functional list. *)
+
+ val app : 'a Effect.t -> 'a t Effect.t
+ (**
+ * Applies the given effect to all elements of the imperative list.
+ * {app} is to be implemented tail recursively.
+ *)
+
+ val find : 'a UnPr.t -> 'a t -> ('a t, 'a t) Sum.t
+ (**
+ * Returns {INR n} where {n} is first node containing an element
+ * satisfying the given predicate or {INL n} where {n} is the last node
+ * in the imperative list. {find} is to be implemented tail
+ * recursively.
+ *)
+
+ val foldl : ('a * 'b -> 'b) -> 'b -> 'a t -> 'b
+ (**
+ * Folds the imperative lists with the given function and starting
+ * value. {foldl} is to be implemented tail recursively.
+ *)
+end = struct
+ datatype 'a t = IN of ('a * 'a t) Option.t Ref.t
+ fun new () = IN (ref NONE)
+ fun get (IN t) = !t
+ fun (IN r) <- t = r := t
+
+ (* The following only use the operations {new}, {get}, and {<-}. *)
+
+ fun fromList l = let
+ val h = new ()
+ fun lp ([], _) = ()
+ | lp (x::xs, t) = let
+ val t' = new ()
+ in
+ t <- SOME (x, t')
+ ; lp (xs, t')
+ end
+ in
+ lp (l, h)
+ ; h
+ end
+
+ fun isEmpty t =
+ not (isSome (get t))
+
+ local
+ fun eat t =
+ case get t of
+ NONE => raise Empty
+ | SOME x => x
+ in
+ fun hd t = #1 (eat t)
+ fun tl t = #2 (eat t)
+ end
+
+ fun push t x = let
+ val n = new ()
+ in
+ n <- get t
+ ; t <- SOME (x, n)
+ end
+
+ fun take t =
+ case get t of
+ NONE => NONE
+ | SOME (x, t') => (t <- get t' ; SOME x)
+
+ fun drop t =
+ ignore (take t)
+
+ fun clearWith e t =
+ case take t of
+ NONE => ()
+ | SOME x => (e x : unit ; clearWith e t)
+
+ fun foldl f x t =
+ case get t of
+ NONE => x
+ | SOME (y, t) =>
+ foldl f (f (y, x)) t
+
+ fun app e =
+ foldl (e o #1) ()
+
+ fun find p t =
+ case get t of
+ NONE => INL t
+ | SOME (x, t') =>
+ if p x then INR t else find p t'
+end
Property changes on: mltonlib/trunk/com/ssh/misc-util/unstable/node.sml
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the MLton-commit
mailing list