Skip to content

Instantly share code, notes, and snippets.

@NickHeiner
Forked from 23Skidoo/Queue.ml
Created April 29, 2012 22:54
Show Gist options
  • Save NickHeiner/2553666 to your computer and use it in GitHub Desktop.
Save NickHeiner/2553666 to your computer and use it in GitHub Desktop.
Purely functional queue in Ocaml
(* Nick Heiner <nth23@cornell.edu> *)
(* Adapted from https://gist.github.com/1347308 *)
(* The func_ prefix is to avoid confusion with OCaml's standard Queue. *)
(* from F# *)
let (|>) g f = f g
type 'a func_queue = Func_Queue of 'a list * 'a list
let empty = Func_Queue ([], [])
let add q elt = match q with
| Func_Queue (front, back) -> Func_Queue (elt::front, back)
(* convenience overload for add *)
let push elt q = add q elt
let peek_tail = function
| Func_Queue ([], []) ->
raise (Invalid_argument "FuncQueue.peek_tail: Empty Queue")
| Func_Queue (hd::tl, _) -> hd
| Func_Queue ([], back) -> List.rev back |> List.hd
(* bit of duplication between this and take *)
let peek = function
| Func_Queue ([], []) -> raise (Invalid_argument "Empty queue!")
| Func_Queue (front, b::bs) -> b
| Func_Queue (front, []) -> let back = List.rev front
in List.hd back
let take = function
| Func_Queue ([], []) -> raise (Invalid_argument "Empty queue!")
| Func_Queue (front, b::bs) -> b, (Func_Queue (front, bs))
| Func_Queue (front, []) -> let back = List.rev front
in (List.hd back, Func_Queue ([], List.tl back))
(* Drops the elements from the head of the list while pred holds *)
let rec drop_if (pred : 'a -> bool) (q : 'a func_queue) : 'a func_queue =
if q = empty then q else
if pred (peek q) then drop_if pred (snd (take q)) else q
let rec fold f init q =
if q = empty then init else
let head, rest = take q in
fold f (f init head) rest
let size q = fold (fun acc _ -> acc + 1) 0 q
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment