0 | module BinaryRandomAccessList
4 | import RandomAccessList
8 | data Tree a = Leaf a | Node Int (Tree a) (Tree a)
9 | data Digit a = Zero | One (Tree a)
12 | data BinaryList a = BL (List (Digit a))
14 | size : Tree a -> Int
16 | size (Node w t1 t2) = w
18 | link : Tree a -> Tree a -> Tree a
19 | link t1 t2 = Node (size t1 + size t2) t1 t2
21 | consTree : Tree a -> List (Digit a) -> List (Digit a)
22 | consTree t [] = [One t]
23 | consTree t (Zero :: ts) = One t :: ts
24 | consTree t1 (One t2 :: ts) = Zero :: consTree (link t1 t2) ts
26 | unconsTree : List (Digit a) -> (Tree a, List (Digit a))
27 | unconsTree [] = assert_total $
idris_crash "empty list"
28 | unconsTree [One t] = (t, [])
29 | unconsTree (One t :: ts) = (t, Zero :: ts)
30 | unconsTree (Zero :: ts) = case unconsTree ts of
31 | (Node _ t1 t2, ts') => (t1, One t2 :: ts')
32 | (Leaf _ , _) => assert_total $
idris_crash "assert_unreachable"
35 | RandomAccessList BinaryList where
37 | isEmpty (BL ts) = isNil ts
39 | cons x (BL ts) = BL (consTree (Leaf x) ts)
40 | head (BL ts) = assert_total $
let (Leaf x, _) = unconsTree ts in x
41 | tail (BL ts) = let (_, ts') = unconsTree ts in BL ts'
43 | lookup i (BL ts) = look i ts
45 | lookTree : Int -> Tree a -> a
46 | lookTree 0 (Leaf x) = x
47 | lookTree i (Leaf x) = assert_total $
idris_crash "bad subscript"
48 | lookTree i (Node w t1 t2) = let hw = assert_total $
w `div` 2
49 | in if i < hw then lookTree i t1 else lookTree (i - hw) t2
51 | look : Int -> List (Digit a) -> a
52 | look i [] = assert_total $
idris_crash "bad subscript"
53 | look i (Zero :: ts) = look i ts
54 | look i (One t :: ts) =
55 | if i < size t then lookTree i t else look (i - size t) ts
57 | update i y (BL ts) = BL (upd i ts)
59 | updTree : Int -> Tree a -> Tree a
60 | updTree 0 (Leaf x) = Leaf y
61 | updTree i (Leaf x) = assert_total $
idris_crash "bad subscript"
62 | updTree i (Node w t1 t2) = let hw = assert_total $
w `div` 2 in
63 | if i < hw then Node w (updTree i t1) t2
64 | else Node w t1 (updTree (i - hw) t2)
66 | upd : Int -> List (Digit a) -> List (Digit a)
67 | upd i [] = assert_total $
idris_crash "bad subscript"
68 | upd i (Zero :: ts) = Zero :: upd i ts
69 | upd i (One t :: ts) =
70 | if i < size t then One (updTree i t) :: ts
71 | else One t :: upd (i - size t) ts