PreviousUpNext

15.4.871  src/lib/src/binary-random-access-list.pkg

## binary-random-access-list.pkg
## Random Access Lists  (due to Chris Okasaki)
##
## -- Allen Leung
#
# Random access lists combine list-style head/tail
# access with the ability to efficiently access any
# list element by number.
#
# This implementation of them is inspired by binary
# numbers, and comes from Chris Okasaki's seminal book
# "Purely Functional Data Structures" Section 9.2.1 (p119)

# Compiled by:
#     src/lib/std/standard.lib

# Compare with:
#     src/lib/src/red-black-numbered-list.pkg 


###          "Fifty years into the First Computing Era
###           some of us in the computing arena have come
###           to realize we've made a false start, and for
###           us to finally be able to produce lasting,
###           correct, beautiful, usable, scalable, enjoyable
###           software that stands the tests of time and
###           moral human endeavor, we need to start over."
###
###                               -- Richard P Gabriel



package binary_random_access_list:  Random_Access_List                  # Random_Access_List    is from   src/lib/src/random-access-list.api
{
   Tree(X)
       = LEAF X
       | NODE ((Tree(X), X, Tree(X)));

   Random_Access_List(X)
       =
       List( (Int, Tree(X) ) );
    
   fun tree_get (LEAF x, 0, _) => x;
       tree_get (LEAF _, _, _) => raise exception INDEX_OUT_OF_BOUNDS;
       tree_get (NODE(_, x, _), 0, _) => x;

       tree_get (NODE (l, x, r), i, n)
           =>
           {   n' = n / 2;

               if   (i <= n'   )   tree_get (l, i - 1,  n');
                              else   tree_get (r, i - 1 - n', n');  fi;
           };
   end;

   fun tree_set (LEAF _, 0, x, _) => LEAF x;
       tree_set (LEAF _, _, _, _) => raise exception INDEX_OUT_OF_BOUNDS;
       tree_set (NODE (l, _, r), 0, x, _) => NODE (l, x, r);

       tree_set (NODE (l, y, r), i, x, n)
           =>
           {   n' = n / 2;

               if (i <= n' ) NODE (tree_set (l, i - 1, x, n'), y, r);
                          else NODE (l, y, tree_set (r, i - 1 - n', x, n'));  fi;
           };
   end;

   empty = [];

   fun null [] =>  TRUE;
       null _  =>  FALSE;
   end;

   fun length rl
       =
       f (rl, 0)
       where
           fun f ([],         n) =>  n;
               f ((m, _) ! l, n) =>  f (l, m+n);
           end;
       end;

   fun cons (x, rl as ((m, t) ! (n, u) ! l))
           => 
           if (m == n)   (m+n+1, NODE (t, x, u)) ! l;
           else          (1, LEAF x) ! rl;
           fi;

       cons (x, rl)
           =>
           (1, LEAF x) ! rl;
   end;

   fun head ((_, LEAF x) ! _) => x;
       head ((_, NODE(_, x, _)) ! _) => x;
       head [] => raise exception EMPTY;
   end;

   fun tail ((_, LEAF x) ! rl)
           =>
           rl;

       tail ((n, NODE (l, x, r)) ! rl)
           =>
           {   n' = n / 2;

               (n', l) ! (n', r) ! rl;
           };

       tail []
           =>
           raise exception EMPTY;
    end;
         
   fun get ([], _)
           =>
           raise exception INDEX_OUT_OF_BOUNDS;

       get ((n, t) ! rl, i)
           =>
           if   (i < n)   tree_get (t, i, n);
           else           get (rl, i-n);
           fi;
   end;

   fun set ([], _, _)
           =>
           raise exception INDEX_OUT_OF_BOUNDS;

       set ((p as (n, t)) ! rl, i, x)
           =>
           if (i < n)   (n, tree_set (t, i, x, n)) ! rl;
           else         p ! set (rl, i-n, x);
           fi;
   end;

   fun map f rl
       = 
       list::map (\\ (n, t) =  (n, g t)) rl
       where
           fun g (LEAF x)         =>  LEAF (f x);
               g (NODE (l, x, r)) =>  NODE (g l, f x, g r);
           end; 
       end;

   fun apply f rl
       =
       list::apply (\\ (_, t) =  g t) rl
       where
           fun g (LEAF x)
                   =>
                   f x;

               g (NODE (l, x, r))
                   =>
                   {   f x;
                       g l;
                       g r;
                   };
           end;
       end;

   fun fold_forward f u rl
       =
       list::fold_forward (\\ ((_, t), x) =  g (t, x)) u rl
       where
           fun g (LEAF x, u)         =>  f (x, u);
               g (NODE (l, x, r), u) =>  g (r, g (l, f (x, u)));
           end;
       end;

   fun fold_backward f u rl
       =
       list::fold_backward (\\ ((_, t), x) =  g (t, x)) u rl
       where 
           fun g (LEAF x, u)         =>  f (x, u);
               g (NODE (l, x, r), u) =>  f (x, g (l, g (r, u)));
           end;
       end;

   fun from_list l =  list::fold_backward cons empty l;
   fun to_list  rl =  fold_backward (!) [] rl;

};



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext