This post describes the F# implementation of the binary random access list from Chris Okasaki’s “Purely functional data structures”.

namespace PurelyFunctionalDataStructures

module BinaryRandomAccessList =

  type Tree<'a> =
    | Leaf of 'a
    | Node of int * Tree<'a> * Tree<'a>

  type t<'a> = list<option<Tree<'a>>>

  let empty() = []

  let isEmpty = List.isEmpty

  let size = function
    | Leaf _ -> 1
    | Node (w, _, _) -> w

  let link t1 t2 = Node(size t1 + size t2, t1, t2)

  let rec consTree = function
    | t, [] -> [Some t]
    | t, None::ts -> Some t :: ts
    | t1, Some t2 :: ts -> None :: consTree ((link t1 t2) , ts)

  let rec unconsTree = function
    | [] -> raise Empty
    | [Some t] -> t, []
    | Some t :: ts -> t, None::ts
    | None::ts ->
        match unconsTree ts with
        | Node(_, t1, t2), ts' -> t1, Some t2::ts'
        | _ -> failwith "should never get there"

  let cons x ts = consTree ((Leaf x), ts)

  let singleton x = empty() |> cons x 

  let head = function
    | Some (Leaf x) :: _ -> x
    | [] -> raise Empty
    | _ -> failwith "should not get there"

  let tail ts =
    let _, ts' = unconsTree ts
    ts'

  let rec lookupTree = function
    | 0, Leaf x -> x
    | i, Leaf x -> raise Subscript
    | i, Node(w, t1, t2) ->
        if i < w / 2 then lookupTree (i, t1) else lookupTree (i - w/2, t2)

  let rec updateTree = function
    | 0, y, Leaf x -> Leaf y
    | i, y, Leaf x -> raise Subscript
    | i, y, Node(w, t1, t2) ->
        if i < w / 2 then
          Node(w, updateTree (i, y, t1) , t2)
        else
          Node(w, t1, updateTree (i - w/2, y, t2))

  let rec lookup i = function
    | [] -> raise Subscript
    | None::ts -> lookup i ts
    | Some t::ts ->
        if i < size t then lookupTree (i, t) else lookup (i - size t) ts

  let rec update i y = function
    | []  -> raise Subscript
    | None::ts -> None :: update i y ts
    | Some t::ts ->
        if i < size t then
          let a = Some <| updateTree (i, y, t)
          a :: ts
        else
          (Some t) :: update (i - size t) y ts

Comments are closed.