This post describes the F# implementation of the Bankers double-ended queue from Chris Okasaki’s “Purely functional data structures”.

namespace PurelyFunctionalDataStructures

module BankersDequeue =

  type t<'a> = {
    C : int // c > 1
    FrontLength : int
    Front : LazyList<'a>
    RBackLength : int
    RBack : LazyList<'a>
  }

  let create c lenf f lenr r = {
    C = c
    FrontLength = lenf
    Front = f
    RBackLength = lenr
    RBack = r
  }

  let empty c = create c 0 (LazyList.empty()) 0 (LazyList.empty())

  let isEmpty q = q.FrontLength=0 && q.RBackLength=0

  let length q = q.FrontLength + q.RBackLength

  let check q =
    let n = length q
    if q.FrontLength > q.C * q.RBackLength + 1 then
      let i= n / 2
      let j = n - i
      let f' = LazyList.take i q.Front
      let r' = LazyList.drop i q.Front |> LazyList.rev |> LazyList.append q.RBack
      create q.C i f' j r'
    elif q.RBackLength > q.C * q.FrontLength + 1 then
      let j = n / 2
      let i = n - j
      let f' = LazyList.take j q.RBack
      let r' = LazyList.drop j q.RBack |> LazyList.rev |> LazyList.append q.Front
      create q.C i f' j r'
    else
      q

  let cons x q =
    create q.C (q.FrontLength+1) (LazyList.cons x q.Front) q.RBackLength q.RBack
    |> check

  let singleton c x = empty c |> cons x

  let head q =
    match q.Front, q.RBack with
    | LazyList.Nil, LazyList.Nil -> raise Empty
    | LazyList.Nil, LazyList.Cons(x, _) -> x
    | LazyList.Cons(x, _), _ -> x

  let tail q =
    match q.Front, q.RBack with
    | LazyList.Nil, LazyList.Nil -> raise Empty
    | LazyList.Nil, LazyList.Cons(x, _) -> empty q.C
    | LazyList.Cons(x, xs), _ ->
        create q.C (q.FrontLength-1) xs q.RBackLength q.RBack
        |> check 

  let snoc x q =
    create q.C q.FrontLength q.Front (q.RBackLength+1) (LazyList.cons x q.RBack)
    |> check

  let last q =
    match q.Front, q.RBack with
    | LazyList.Nil, LazyList.Nil -> raise Empty
    | _, LazyList.Cons(x, _) ->  x
    | LazyList.Cons(x, _), LazyList.Nil-> x

  let init q =
    match q.Front, q.RBack with
    | LazyList.Nil, LazyList.Nil -> raise Empty
    | _, LazyList.Nil -> empty q.C
    | _, LazyList.Cons(x, xs) ->
        create q.C q.FrontLength q.Front (q.RBackLength-1) xs
        |> check 

Comments are closed.