I took Okasaki to perform catheterized lists and reworked it a bit to avoid problems with boolean blindness. In addition, the data structure itself remains unchanged:
functor CatList (Q : QUEUE) :> CAT_LIST =
struct
(* private stuff, not exposed by CAT_LIST *)
structure L = Lazy
structure O = Option (* from basis library *)
datatype 'a cons = ::: of 'a * 'a cons L.lazy Q.queue
infixr 5 :::
(* Q.snoc : 'a Q.queue * 'a -> 'a Q.queue *)
fun link (x ::: xs, ys) = x ::: Q.snoc (xs, ys)
(* L.delay : ('a -> 'b) -> ('a -> 'b L.lazy)
* L.force : 'a L.lazy -> 'a
* Q.uncons : 'a Q.queue -> ('a * 'a Q.queue lazy) option *)
fun linkAll (xs, ys) =
let
val xs = L.force xs
val ys = L.force ys
in
case Q.uncons ys of
NONE => xs
| SOME ys => link (xs, L.delay linkAll ys)
end
(* public stuff, exposed by CAT_LIST *)
type 'a list = 'a cons option
val empty = NONE
(* L.pure : 'a -> 'a L.lazy *)
fun append (xs, NONE) = xs
| append (NONE, xs) = xs
| append (SOME xs, SOME ys) = SOME (link (xs, L.pure ys))
(* Q.empty : 'a Q.queue *)
fun cons (x, xs) = append (SOME (x ::: Q.empty), xs)
fun snoc (xs, x) = append (xs, SOME (x ::: Q.empty))
(* O.map : ('a -> 'b) -> ('a option -> 'b option) *)
fun uncons NONE = NONE
| uncons (SOME (x ::: xs)) = SOME (x, L.delay (O.map linkAll) (Q.uncons xs))
end
In his book Okasaki claims that the implementation of the queue with the operations O(1)(in the worst case, or depreciation) appendand unconsamortized O(1).
? ( O(1)), append uncons O(1) . linkAll L.delay, . ( ) ?