File: randlist.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (122 lines) | stat: -rw-r--r-- 3,406 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(*
 * Random Access Lists  (due to Chris Okasaki)
 *
 * -- Allen
 *)

signature RANDOM_ACCESS_LIST =
sig

   type 'a rand_list

                 (* O(1) operations *)
   val empty  : 'a rand_list           
   val length : 'a rand_list -> int
   val null   : 'a rand_list -> bool
   val cons   : 'a * 'a rand_list -> 'a rand_list
   val hd     : 'a rand_list -> 'a
   val tl     : 'a rand_list -> 'a rand_list
  
                 (* O(log n) operations *)
   val sub       : 'a rand_list * int -> 'a
   val update    : 'a rand_list * int * 'a -> 'a rand_list
  
                 (* O(n) operations *)
   val fromList  : 'a list -> 'a rand_list
   val toList    : 'a rand_list -> 'a list

                 (* O(n) operations *)
   val map       : ('a -> 'b) -> 'a rand_list -> 'b rand_list
   val app       : ('a -> unit) -> 'a rand_list -> unit
   val foldl     : ('a * 'b -> 'b) -> 'b -> 'a rand_list -> 'b
   val foldr     : ('a * 'b -> 'b) -> 'b -> 'a rand_list -> 'b
end  

structure RandomAccessList :> RANDOM_ACCESS_LIST =
struct

   datatype 'a tree = LEAF of 'a | NODE of 'a tree * 'a * 'a tree

   type 'a rand_list = (int * 'a tree) list
    
   fun tree_sub (LEAF x,0,_) = x
     | tree_sub (LEAF _,_,_) = raise Subscript
     | tree_sub (NODE(_,x,_),0,_) = x
     | tree_sub (NODE(l,x,r),i,N) = 
       let val N' = N div 2
       in  if i <= N' then tree_sub(l,i-1,N')
                      else tree_sub(r,i-1-N',N')
       end

   fun tree_update (LEAF _,0,x,_) = LEAF x
     | tree_update (LEAF _,_,_,_) = raise Subscript
     | tree_update (NODE(l,_,r),0,x,_) = NODE(l,x,r)
     | tree_update (NODE(l,y,r),i,x,N) = 
       let val N' = N div 2
       in  if i <= N' then NODE(tree_update(l,i-1,x,N'),y,r)
                      else NODE(l,y,tree_update(r,i-1-N',x,N'))
       end

   val empty = []

   fun null [] = true | null _ = false

   fun length rl =
   let fun f([],n) = n
         | f((m,_)::l,n) = f(l,m+n)
   in  f(rl,0)
   end

   fun cons (x, rl as ((m,t)::(n,u)::l)) = 
        if m = n then (m+n+1,NODE(t,x,u))::l
                 else (1,LEAF x)::rl
     | cons (x, rl) = (1,LEAF x)::rl

   fun hd ((_,LEAF x)::_) = x
     | hd ((_,NODE(_,x,_))::_) = x
     | hd [] = raise Empty

   fun tl ((_,LEAF x)::rl) = rl
     | tl ((n,NODE(l,x,r))::rl) = 
       let val n' = n div 2
       in  (n',l)::(n',r)::rl
       end
     | tl [] = raise Empty
         
   fun sub([],_)        = raise Subscript
     | sub((n,t)::rl,i) = if i < n then tree_sub(t,i,n)
                          else sub(rl,i-n)

   fun update([],_,_)   = raise Subscript
     | update((p as (n,t))::rl,i,x) =
         if i < n then (n,tree_update(t,i,x,n))::rl
         else p::update(rl,i-n,x)

   fun map f rl = 
   let fun g (LEAF x)      = LEAF(f x)
         | g (NODE(l,x,r)) = NODE(g l,f x,g r)
   in  List.map (fn (n,t) => (n,g t)) rl
   end

   fun app f rl =
   let fun g (LEAF x)      = f x
         | g (NODE(l,x,r)) = (f x; g l; g r)
   in  List.app (fn (_,t) => g t) rl
   end

   fun foldl f u rl =
   let fun g (LEAF x,u)      = f(x,u)
         | g (NODE(l,x,r),u) = g(r,g(l,f(x,u)))
   in  List.foldl (fn ((_,t),x) => g(t,x)) u rl
   end

   fun foldr f u rl =
   let fun g (LEAF x,u)      = f(x,u)
         | g (NODE(l,x,r),u) = f(x,g(l,g(r,u)))
   in  List.foldr (fn ((_,t),x) => g(t,x)) u rl
   end

   fun fromList l = List.foldr cons empty l
   fun toList rl  = foldr op:: [] rl
end