Data structure slides and source code

master
Levi Pearson 2014-06-10 22:58:26 -06:00
commit 2d9121e663
19 changed files with 2371 additions and 0 deletions

22
DenseNat.hs Normal file
View File

@ -0,0 +1,22 @@
module DenseNat where
data Digit = Zero | One deriving (Show, Ord, Eq, Enum)
type DenseNat = [Digit] -- increasing order of significance
inc :: DenseNat -> DenseNat
inc [] = [One]
inc (Zero : ds) = One : ds
inc (One : ds) = Zero : inc ds -- carry
dec :: DenseNat -> DenseNat
dec [One] = []
dec (One : ds) = Zero : ds
dec (Zero : ds) = One : dec ds -- borrow
add :: DenseNat -> DenseNat -> DenseNat
add ds [] = ds
add [] ds = ds
add (d : ds1) (Zero : ds2) = d : add ds1 ds2
add (Zero : ds1) (d : ds2) = d : add ds1 ds2
add (One : ds1) (One : ds2) = Zero : inc (add ds1 ds2) -- carry

97
HAMT.hs Normal file
View File

@ -0,0 +1,97 @@
module HAMT where
import Data.Bits
import Data.Word
import Prelude hiding (lookup, (++))
import Data.Vector (Vector, singleton, unsafeDrop, unsafeIndex,
unsafeTake, unsafeUpdate, (++))
type Key = Word
type Bitmap = Word
type Shift = Int
type Subkey = Int -- we need to use this to do shifts, so an Int it is
data HAMT a = Empty
| BitmapIndexed {-# UNPACK #-} !Bitmap !(Vector (HAMT a))
| Leaf {-# UNPACK #-} !Key a
| Full {-# UNPACK #-} !(Vector (HAMT a))
deriving (Show)
-- These architecture dependent constants
bitsPerSubkey :: Int
bitsPerSubkey = floor . logBase 2 . fromIntegral . bitSize $ (undefined :: Word)
subkeyMask :: Bitmap
subkeyMask = 1 `shiftL` bitsPerSubkey - 1
maskIndex :: Bitmap -> Bitmap -> Int
maskIndex b m = popCount (b .&. (m - 1))
mask :: Key -> Shift -> Bitmap
mask k s = shiftL 1 (subkey k s)
{-# INLINE subkey #-}
subkey :: Key -> Shift -> Int
subkey k s = fromIntegral $ shiftR k s .&. subkeyMask
empty :: HAMT a
empty = Empty
lookup :: Key -> HAMT a -> Maybe a
lookup k t = lookup' k 0 t
lookup' :: Key -> Shift -> HAMT a -> Maybe a
lookup' k s t
= case t of
Empty -> Nothing
Leaf kx x
| k == kx -> Just x
| otherwise -> Nothing
BitmapIndexed b v ->
let m = mask k s in
if b .&. m == 0
then Nothing
else lookup' k (s+bitsPerSubkey) (unsafeIndex v (maskIndex b m))
Full v -> lookup' k (s+bitsPerSubkey) (unsafeIndex v (subkey k s))
insert :: Key -> a -> HAMT a -> HAMT a
insert k v t = insert' k 0 v t
insert' :: Key -> Shift -> a -> HAMT a -> HAMT a
insert' kx s x t
= case t of
Empty -> Leaf kx x
Leaf ky y
| ky == kx -> Leaf kx x
| otherwise ->
insert' kx s x $ BitmapIndexed (mask ky s) (singleton t)
BitmapIndexed b v -> {-# SCC "i-Bitmap" #-}
let m = mask kx s
i = maskIndex b m in
if b .&. m == 0
then let l = Leaf kx x
v' = unsafeTake i v ++ singleton l ++ unsafeDrop i v
b' = b .|. m in
if b' == 0xFFFFFFFF
then Full v'
else BitmapIndexed b' v'
else {-# SCC "i-Bitmap-conflict" #-}
let st = unsafeIndex v i
st' = insert' kx (s+bitsPerSubkey) x st
v' = {-# SCC "i-Bitmap-update" #-}
unsafeUpdate v (singleton (i, st'))
in BitmapIndexed b v'
Full v -> {-# SCC "i-Full" #-}
let i = subkey kx s
st = unsafeIndex v i
st' = insert' kx (s+bitsPerSubkey) x st
v' = {-# SCC "i-Full-update" #-}
unsafeUpdate v (singleton (i, st'))
in Full v'
-- lazy, but that's not necessarily a bad thing
fromList :: [(Key, a)] -> HAMT a
fromList = foldl (flip $ uncurry insert) empty

216
HON.hs Normal file
View File

@ -0,0 +1,216 @@
module HigherOrderNested where
{- Start with a standard data type
data Nat = Zero
| Succ Nat
deriving (Eq, Show)
-}
-- Decompose it into separate types
data Zero = NZero
deriving (Eq, Show)
data Succ nat = Succ nat
deriving (Eq, Show)
-- And define a nested combining type
data Nats nat = NNil
| NCons nat (Nats (Succ nat))
deriving (Eq, Show)
{- Some examples of instances of this type:
NCons NZero NNil
NCons NZero (NCons (Succ NZero) NNil)
NCons NZero (NCons (Succ NZero) (NCons (Succ (Succ NZero)) NNil))
-}
{- The Stack type, analogous to Nat
data Stack a = Empty
| Push a (Stack a)
deriving (Eq, Show)
-}
-- Decompose to separate types
data Empty a = Empty
deriving (Eq, Show)
data Push stack a = Push a (stack a)
deriving (Eq, Show)
-- Define a nested combining type
data Stacks stack a = SNil
| SCons (stack a) (Stacks (Push stack) a)
deriving (Eq, Show)
{- Some examples:
SCons Empty SNil
SCons Empty (SCons (Push 'a' Empty) SNil)
SCons Empty (SCons (Push 'a' Empty) (SCons (Push 'a' (Push 'b' Empty)) SNil))
-}
{- Perfect Binary Leaf Trees
data Bush a = Leaf a
| Fork (Bush a) (Bush a)
deriving (Eq, Show)
-}
-- Decomposed Perfect Binary Leaf Trees
data Leaf a = Leaf a
deriving (Eq, Show)
data Fork bush a = Fork (bush a) (bush a)
deriving (Eq, Show)
{- Uses a zeroless 1-2 representation to eliminate overhead of numerical
nodes with no data.
Counting: 1, 2, 11, 21, 12, 22, 111, 211, 121, 221, 112, 212, 122, 222
Note that only the first One constructor can directly store the
Leaf type; all others will use Fork^n Leaf, which guarantees that
our "Perfect" invariant holds.
Each recursive instantiation of the type occurs with another level
of Fork wrapping the bush type; One uses that level directly, while
Two adds an extra Fork level to it.
-}
data RandomAccessList bush a
= Nil
| One (bush a) (RandomAccessList (Fork bush) a)
| Two (Fork bush a) (RandomAccessList (Fork bush) a)
deriving (Eq, Show)
type IxSequence = RandomAccessList Leaf
-- Consing to the front increments the number with a Leaf as data
cons :: a -> IxSequence a -> IxSequence a
cons a = incr (Leaf a)
incr :: bush a
-> RandomAccessList bush a
-> RandomAccessList bush a
incr b Nil = One b Nil -- inc 0 = 1
incr b1 (One b2 ds) = Two (Fork b1 b2) ds -- inc 1.. = 2..
incr b1 (Two b2 ds) = One b1 (incr b2 ds) -- inc 2d.. = 1(inc d)..
-- This is used to eliminate leading zeros
zero :: RandomAccessList (Fork bush) a
-> RandomAccessList bush a
zero Nil = Nil -- 0 = 0
zero (One b ds) = Two b (zero ds) -- 01.. = 20.
zero (Two (Fork b1 b2) ds) = Two b1 (One b2 ds) -- 02.. = 21.
-- Removing from the front decrements the number and removes a Leaf
front :: IxSequence a -> (a, IxSequence a)
front Nil = error "IxSequence empty"
front (One (Leaf a) ds) = (a, zero ds) -- dec 1.. = 0..
front (Two (Fork (Leaf a) b) ts) = (a, One b ts) -- dec 2.. = 1..
fromList :: [a] -> IxSequence a
fromList = foldr cons Nil
{- A recursive (top-down) solution
unleaf :: Leaf a -> [a]
unleaf (Leaf a) = [a]
unfork :: (bush a -> [a]) -> Fork bush a -> [a]
unfork flatten (Fork l r) = flatten l ++ flatten r
listify :: (bush a -> [a]) -> RandomAccessList bush a -> [a]
listify _ Nil = []
listify flatten (One b ds) = flatten b ++ listify (unfork flatten) ds
listify flatten (Two b ds) = unfork flatten b ++ listify (unfork flatten) ds
toList :: IxSequence a -> [a]
toList = listify unleaf
-}
{- A recursive (top-down) solution with Type Classes
class Flatten bush where
flatten :: bush a -> [a]
instance Flatten Leaf where
flatten (Leaf a) = [a]
instance (Flatten bush) => Flatten (Fork bush) where
flatten (Fork l r) = flatten l ++ flatten r
listify :: (Flatten bush) => RandomAccessList bush a -> [a]
listify Nil = []
listify (One b ds) = flatten b ++ listify ds
listify (Two b ds) = flatten b ++ listify ds
toList :: IxSequence a -> [a]
toList = listify
-}
{- An iterative (bottom-up) solution; linear time bound -}
listify :: RandomAccessList bush a -> [bush a]
listify Nil = []
listify (One b ds) = b : unforks (listify ds)
listify (Two b ds) = unforks (b : listify ds)
unforks :: [Fork bush a] -> [bush a]
unforks [] = []
unforks (Fork b1 b2 : ts) = b1 : b2 : unforks ts
toList :: IxSequence a -> [a]
toList s = [a | Leaf a <- listify s]
{- Examples:
> fromList[1..5]
One (Leaf 1)
(Two (Fork (Fork (Leaf 2) (Leaf 3))
(Fork (Leaf 4) (Leaf 5)))
Nil)
12 = 1*1 + 2*2 = 1 + 4 = 5
> fromList [1..20]
Two (Fork (Leaf 1) (Leaf 2)) -- 0, 1
(One (Fork (Leaf 3) (Leaf 4)) -- 2, 3
(Two (Fork (Fork (Fork (Leaf 5) (Leaf 6)) -- 4, 11
(Fork (Leaf 7) (Leaf 8)))
(Fork (Fork (Leaf 9) (Leaf 10))
(Fork (Leaf 11) (Leaf 12))))
(One (Fork (Fork (Fork (Leaf 13) (Leaf 14)) -- 12, 19
(Fork (Leaf 15) (Leaf 16)))
(Fork (Fork (Leaf 17) (Leaf 18))
(Fork (Leaf 19) (Leaf 20))))
Nil)))
2121 = 2*1 + 1*2 + 2*4 + 1*8 = 2 + 2 + 8 + 8 = 20
tree size at each rank is d*2^r
-}
{-
Searching:
lookup 0 (One (Leaf x) _) = x
lookup 0 (One (Fork t1 t2) ds) = lookup 0 (One )
-}
class FindB bush where
findB :: Int -> Int -> bush a -> a
instance FindB Leaf where
findB _ _ (Leaf x) = x
instance (FindB bush) => FindB (Fork bush) where
findB i s (Fork lb rb)
| i < s`div`2 = findB i (s`div`2) lb
| otherwise = findB i (s`div`2) rb
find :: Int -> IxSequence a -> a
find = find' 0
find' :: (FindB bush) => Int -> Int
-> RandomAccessList bush a -> a
find' _ _ Nil = error "Not found"
find' r i (One b ds)
| i < 2^r = findB i (2^r) b
| otherwise = find' (i-2^r) (r+1) ds
find' r i (Two b ds)
| i < 2*2^r = findB i (2*2^r) b
| otherwise = find' (i-2*2^r) (r+1) ds

31
Nested.hs Normal file
View File

@ -0,0 +1,31 @@
module Nested where
data Fork t = Fork t t
deriving (Show, Eq)
data RandList t = Nil
| Zero (RandList (Fork t))
| One t (RandList (Fork t))
deriving (Show, Eq)
cons :: a -> RandList a -> RandList a
cons x Nil = One x Nil
cons x1 (Zero ds) = One x1 ds
cons x1 (One x2 ds) = Zero (cons (Fork x1 x2) ds)
front :: RandList a -> (a, RandList a)
front Nil = error "Empty RandList"
front (One x Nil) = (x, Nil)
front (One x ds) = (x, Zero ds)
front (Zero ds) = (x1, One x2 ds')
where (Fork x1 x2, ds') = front ds
find :: Int -> RandList a -> a
find 0 Nil = error "Not found"
find 0 (One x _) = x
find i (One _ ds) = find (i-1) (Zero ds)
find i (Zero ds) = if i`mod`2 == 0 then x else y
where (Fork x y) = find (i`div`2) ds
fromList :: [a] -> RandList a
fromList = foldr cons Nil

1031
Presn.md Normal file

File diff suppressed because it is too large Load Diff

22
Queue1.hs Normal file
View File

@ -0,0 +1,22 @@
module Queue1 where
import StrictList as L
data Queue a = Q { left :: StrictList a
, leftLen :: !Int
, right :: StrictList a
, rightLen :: !Int
} deriving (Show, Eq)
empty :: Queue a
empty = Q Empty 0 Empty 0
length :: Queue a -> Int
length (Q _ ll _ rl) = ll + rl
insert :: a -> Queue a -> Queue a
insert e (Q l ll r rl) = Q l ll (e :$ r) (rl + 1)
remove :: Queue a -> (a, Queue a)
remove (Q Empty _ r rl) = remove (Q (L.reverse r) rl Empty 0)
remove (Q l ll r rl) = (L.head l, Q (L.tail l) (ll - 1) r rl)

33
Queue2.hs Normal file
View File

@ -0,0 +1,33 @@
module Queue2 where
import Prelude hiding (length)
-- Invariant: |R| <= |L|
-- Invariant is preserved via the makeQ function
data Queue a = Q { left :: [a]
, leftLen :: !Int
, right :: [a]
, rightLen :: !Int
} deriving (Show, Eq)
empty :: Queue a
empty = Q [] 0 [] 0
length :: Queue a -> Int
length (Q _ ll _ rl) = ll + rl
insert :: a -> Queue a -> Queue a
insert e (Q l ll r rl) = makeQ (Q l ll (e : r) (rl + 1))
remove :: Queue a -> (a, Queue a)
remove (Q l ll r rl) = (head l, makeQ (Q (tail l) (ll - 1) r rl))
makeQ :: Queue a -> Queue a
makeQ q@(Q l ll r rl)
| rl <= ll = q
| otherwise = Q (rot l r []) (ll + rl) [] 0
rot :: [a] -> [a] -> [a] -> [a]
rot [] r a = head r : a
rot l r a = head l : rot (tail l) (tail r) (head r : a)

55
Queue2.txt Normal file
View File

@ -0,0 +1,55 @@
--Load Queue2.hs - lazy rebuilding queue
:l Queue2.hs
--Start ghc-vis
:vis
let x = empty
:view x
--Insert a value - view new queue; we already triggered the reverse
let y = insert 1 x
:view y
--Remove the value - forces the evaluation in y, but we discard the new tree
let (z,_) = remove y
print z
:update
--Add another element to y; now there's one in the right list
let a = insert 2 y
:view a
--Add one more, and we trigger the swap again
let b = insert 3 a
:view b
--We can add 3 more and still not swap
let c = insert 6 $ insert 5 $ insert 4 b
:view c
--One more, and now we trigger the swap
let d = insert 7 c
:view d
--Let's remove one by one and see how evaluation progresses
let (e,f) = remove d
print e
:view f
let (g,h) = remove f
print g
:view h
let (i,j) = remove h
print i
:view j
let (k,l) = remove j
print k
:view l
let (m,n) = remove l
print m
:view n

1
Queue3.hs Normal file
View File

@ -0,0 +1 @@
module Queue3 where

81
RB1.hs Normal file
View File

@ -0,0 +1,81 @@
module RedBlack1 where
{- Version 1, 'untyped' -}
data Color = R | B deriving Show
data RB a = E | T Color (RB a) a (RB a) deriving Show
{- Insertion and membership test as by Okasaki -}
insert :: Ord a => a -> RB a -> RB a
insert x s =
T B a z b
where
T _ a z b = ins s
ins E = T R E x E
ins s'@(T B a' y b')
| x<y = balance (ins a') y b'
| x>y = balance a' y (ins b')
| otherwise = s'
ins s'@(T R a' y b')
| x<y = T R (ins a') y b'
| x>y = T R a' y (ins b')
| otherwise = s'
member :: Ord a => a -> RB a -> Bool
member _ E = False
member x (T _ a y b)
| x < y = member x a
| x > y = member x b
| otherwise = True
{- balance: first equation is new,
to make it work with a weaker invariant -}
balance :: RB a -> a -> RB a -> RB a
balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d)
balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)
balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)
balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)
balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)
balance a x b = T B a x b
{- deletion a la SMK -}
delete :: Ord a => a -> RB a -> RB a
delete x t =
case del t of {T _ a y b -> T B a y b; _ -> E}
where
del E = E
del (T _ a y b)
| x<y = delformLeft a y b
| x>y = delformRight a y b
| otherwise = app a b
delformLeft a@(T B _ _ _) y b = balleft (del a) y b
delformLeft a y b = T R (del a) y b
delformRight a y b@(T B _ _ _) = balright a y (del b)
delformRight a y b = T R a y (del b)
balleft :: RB a -> a -> RB a -> RB a
balleft (T R a x b) y c = T R (T B a x b) y c
balleft bl x (T B a y b) = balance bl x (T R a y b)
balleft bl x (T R (T B a y b) z c) = T R (T B bl x a) y (balance b z (sub1 c))
balright :: RB a -> a -> RB a -> RB a
balright a x (T R b y c) = T R a x (T B b y c)
balright (T B a x b) y bl = balance (T R a x b) y bl
balright (T R a x (T B b y c)) z bl = T R (balance (sub1 a) x b) y (T B c z bl)
sub1 :: RB a -> RB a
sub1 (T B a x b) = T R a x b
sub1 _ = error "invariance violation"
app :: RB a -> RB a -> RB a
app E x = x
app x E = x
app (T R a x b) (T R c y d) =
case app b c of
T R b' z c' -> T R(T R a x b') z (T R c' y d)
bc -> T R a x (T R bc y d)
app (T B a x b) (T B c y d) =
case app b c of
T R b' z c' -> T R(T B a x b') z (T B c' y d)
bc -> balleft a x (T B bc y d)
app a (T R b x c) = T R (app a b) x c
app (T R a x b) c = T R a x (app b c)

179
RB2.hs Normal file
View File

@ -0,0 +1,179 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module RedBlack2 where
data Unit a = E deriving Show
type Tr t a = (t a,a,t a)
data Red t a = C (t a) | R (Tr t a)
instance (Show (t a), Show a) => Show (Red t a)
where showsPrec _ (C t) = shows t
showsPrec _ (R(a,b,c)) =
("R("++) . shows a . (","++) . shows b . (","++) . shows c . (")"++)
data AddLayer t a = B(Tr(Red t) a) deriving Show
data RB t a = Base (t a) | Next (RB (AddLayer t) a)
instance (Show (t a),Show a) => Show (RB t a)
where
show (Base t) = show t
show (Next t) = show t
type Tree a = RB Unit a
empty :: Tree a
empty = Base E
type RR t a = Red (Red t) a
type RL t a = Red (AddLayer t) a
member :: Ord a => a -> Tree a -> Bool
member x t = rbmember x t (const False)
rbmember :: Ord a => a -> RB t a -> (t a->Bool) -> Bool
rbmember _ (Base t) m = m t
rbmember x (Next u) m = rbmember x u (bmem x m)
bmem :: Ord a => a -> (t a->Bool) -> AddLayer t a -> Bool
bmem x m (B(l,y,r))
| x<y = rmem x m l
| x>y = rmem x m r
| otherwise = True
rmem :: Ord a => a -> (t a->Bool) -> Red t a->Bool
rmem _ m (C t) = m t
rmem x m (R(l,y,r))
| x<y = m l
| x>y = m r
| otherwise = True
insert :: Ord a => a -> Tree a -> Tree a
insert = rbinsert
class Insertion t where ins :: Ord a => a -> t a -> Red t a
instance Insertion Unit where ins x E = R(E,x,E)
rbinsert :: (Ord a,Insertion t) => a -> RB t a -> RB t a
rbinsert x (Next t) = Next (rbinsert x t)
rbinsert x (Base t) = blacken(ins x t)
blacken :: Red t a -> RB t a
blacken (C u) = Base u
blacken (R(a,x,b)) = Next(Base(B(C a,x,C b)))
balanceL :: RR t a -> a -> Red t a -> RL t a
balanceL (R(R(a,x,b),y,c)) z d = R(B(C a,x,C b),y,B(c,z,d))
balanceL (R(a,x,R(b,y,c))) z d = R(B(a,x,C b),y,B(C c,z,d))
balanceL (R(C a,x,C b)) z d = C(B(R(a,x,b),z,d))
balanceL (C a) x b = C(B(a,x,b))
balanceR :: Red t a -> a -> RR t a -> RL t a
balanceR a x (R(R(b,y,c),z,d)) = R(B(a,x,C b),y,B(C c,z,d))
balanceR a x (R(b,y,R(c,z,d))) = R(B(a,x,b),y,B(C c,z,C d))
balanceR a x (R(C b,y,C c)) = C(B(a,x,R(b,y,c)))
balanceR a x (C b) = C(B(a,x,b))
instance Insertion t => Insertion (AddLayer t) where
ins x t@(B(l,y,r))
| x<y = balance(ins x l) y (C r)
| x>y = balance(C l) y (ins x r)
| otherwise = C t
instance Insertion t => Insertion (Red t) where
ins x (C t) = C(ins x t)
ins x t@(R(a,y,b))
| x<y = R(ins x a,y,C b)
| x>y = R(C a,y,ins x b)
| otherwise = C t
balance :: RR t a -> a -> RR t a -> RL t a
balance (R a) y (R b) = R(B a,y,B b)
balance (C a) x b = balanceR a x b
balance a x (C b) = balanceL a x b
class Append t where app :: t a -> t a -> Red t a
instance Append Unit where app _ _ = C E
instance Append t => Append (AddLayer t) where
app (B(a,x,b)) (B(c,y,d)) = threeformB a x (appRed b c) y d
threeformB :: Red t a -> a -> RR t a -> a -> Red t a -> RL t a
threeformB a x (R(b,y,c)) z d = R(B(a,x,b),y,B(c,z,d))
threeformB a x (C b) y c = balleftB (C a) x (B(b,y,c))
appRed :: Append t => Red t a -> Red t a -> RR t a
appRed (C x) (C y) = C(app x y)
appRed (C t) (R(a,x,b)) = R(app t a,x,C b)
appRed (R(a,x,b)) (C t) = R(C a,x,app b t)
appRed (R(a,x,b))(R(c,y,d)) = threeformR a x (app b c) y d
threeformR:: t a -> a -> Red t a -> a -> t a -> RR t a
threeformR a x (R(b,y,c)) z d = R(R(a,x,b),y,R(c,z,d))
threeformR a x (C b) y c = R(R(a,x,b),y,C c)
balleft :: RR t a -> a -> RL t a -> RR (AddLayer t) a
balleft (R a) y c = R(C(B a),y,c)
balleft (C t) x (R(B(a,y,b),z,c)) = R(C(B(t,x,a)),y,balleftB (C b) z c)
balleft b x (C t) = C (balleftB b x t)
balleftB :: RR t a -> a -> AddLayer t a -> RL t a
balleftB bl x (B y) = balance bl x (R y)
balright :: RL t a -> a -> RR t a -> RR (AddLayer t) a
balright a x (R b) = R(a,x,C(B b))
balright (R(a,x,B(b,y,c))) z (C d) = R(balrightB a x (C b),y,C(B(c,z,d)))
balright (C t) x b = C (balrightB t x b)
balrightB :: AddLayer t a -> a -> RR t a -> RL t a
balrightB (B y) = balance (R y)
class Append t => DelRed t where
delTup :: Ord a => a -> Tr t a -> Red t a
delLeft :: Ord a => a -> t a -> a -> Red t a -> RR t a
delRight :: Ord a => a -> Red t a -> a -> t a -> RR t a
class Append t => Del t where
del :: Ord a => a -> AddLayer t a -> RR t a
class (DelRed t, Del t) => Deletion t
instance DelRed Unit where
delTup z t@(_,x,_) = if x==z then C E else R t
delLeft _ _ y b = R(C E,y,b)
delRight _ a y _ = R(a,y,C E)
instance Deletion t => DelRed (AddLayer t) where
delTup z (a,x,b)
| z<x = balleftB (del z a) x b
| z>x = balrightB a x (del z b)
| otherwise = app a b
delLeft x a = balleft (del x a)
delRight x a y b = balright a y (del x b)
instance DelRed t => Del t where
del z (B(a,x,b))
| z<x = delformLeft a
| z>x = delformRight b
| otherwise = appRed a b
where delformLeft(C t) = delLeft z t x b
delformLeft(R t) = R(delTup z t,x,b)
delformRight(C t) = delRight z a x t
delformRight(R t) = R(a,x,delTup z t)
instance Deletion t => Deletion (AddLayer t)
instance Deletion Unit
rbdelete :: (Ord a,Deletion t) => a -> RB (AddLayer t) a -> RB t a
rbdelete x (Next t) = Next (rbdelete x t)
rbdelete x (Base t) = blacken2 (del x t)
blacken2 :: RR t a -> RB t a
blacken2 (C(C t)) = Base t
blacken2 (C(R(a,x,b))) = Next(Base(B(C a,x,C b)))
blacken2 (R p) = Next(Base(B p))
delete:: Ord a => a -> Tree a -> Tree a
delete x (Next u) = rbdelete x u
delete _ _ = empty

204
RB3.hs Normal file
View File

@ -0,0 +1,204 @@
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
module RedBlack3 where
type Tr t a b = (t a b, a, t a b)
data Red t a b = C (t a b) | R (Tr t a b)
data Black a b = E | B (Tr (Red Black) a [b])
instance Show a => Show (Black a b) where
showsPrec _ E = ('E':)
showsPrec _ (B (a, x, b)) = ("B(" ++) . showRed a . ("," ++) . shows x .
("," ++) . showRed b . (")" ++)
showRed :: forall t a b. (Show (t a b), Show a)
=> Red t a b
-> ShowS
showRed (C x) = shows x
showRed (R (a, x, b)) = ("R(" ++) . shows a . ("," ++) . shows x . ("," ++) .
shows b . (")" ++)
type RR a b = Red (Red Black) a b
inc :: Black a b
-> Black a [b]
inc = tickB
{- tickB is the identity,
but it allows us to replace that bogus type variable -}
tickB :: Black a b
-> Black a c
tickB E = E
tickB (B (a, x, b)) = B (tickR a, x, tickR b)
tickR :: Red Black a b
-> Red Black a c
tickR (C t) = C (tickB t)
tickR (R (a, x, b)) = R (tickB a, x, tickB b)
data Tree a = forall b . ENC (Black a b)
instance Show a => Show (Tree a)
where show (ENC t) = show t
empty :: Tree a
empty = ENC E
insert :: Ord a
=> a
-> Tree a
-> Tree a
insert x (ENC t) = ENC (blacken (insB x t))
blacken :: Red Black a b
-> Black a b
blacken (C u) = u
blacken (R (a, x, b)) = B (C (inc a), x, C (inc b))
insB :: Ord a
=> a
-> Black a b
-> Red Black a b
insB x E = R (E, x, E)
insB x t@(B (a, y, b))
| x < y = balanceL (insR x a) y b
| x > y = balanceR a y (insR x b)
| otherwise = C t
insR :: Ord a
=> a
-> Red Black a b
-> RR a b
insR x (C t) = C (insB x t)
insR x t@(R (a, y, b))
| x < y = R (insB x a, y, C b)
| x > y = R (C a, y, insB x b)
| otherwise = C t
balanceL :: RR a [b]
-> a
-> Red Black a [b]
-> Red Black a b
balanceL (R (R (a, x, b), y, c)) z d = R (B (C a, x, C b), y, B (c, z, d))
balanceL (R (a, x, R (b, y, c))) z d = R (B (a, x, C b), y, B (C c, z, d))
balanceL (R (C a, x, C b)) z d = C (B (R (a, x, b), z, d))
balanceL (C a) x b = C (B (a, x, b))
balanceR :: Red Black a [b]
-> a
-> RR a [b]
-> Red Black a b
balanceR a x (R (R (b, y, c), z, d)) = R (B (a, x, C b), y, B (C c, z, d))
balanceR a x (R (b, y, R (c, z, d))) = R (B (a, x, b), y, B (C c, z, C d))
balanceR a x (R (C b, y, C c)) = C (B (a, x, R (b, y, c)))
balanceR a x (C b) = C (B (a, x, b))
delete :: Ord a
=> a
-> Tree a
-> Tree a
delete x (ENC t) =
case delB x t of
R p -> ENC (B p)
C (R (a, x', b)) -> ENC (B (C a, x', C b))
C (C q) -> ENC q
delB :: Ord a
=> a
-> Black a b
-> RR a [b]
delB _ E = C (C E)
delB x (B (a, y, b))
| x < y = delfromL a
| x > y = delfromR b
| otherwise = appendR a b
where delfromL (R t) = R (delT x t, y, b)
delfromL (C E) = R (C E, y, b)
delfromL (C t) = balL (delB x t) y b
delfromR (R t) = R (a, y, delT x t)
delfromR (C E) = R (a, y, C E)
delfromR (C t) = balR a y (delB x t)
delT :: Ord a
=> a
-> Tr Black a b
-> Red Black a b
delT x t@(a,y,b)
| x < y = delfromL a
| x > y = delfromR b
| otherwise = append a b
where delfromL (B _) = balLeB (delB x a) y b
delfromL _ = R t
delfromR (B _) = balRiB a y (delB x b)
delfromR _ = R t
balLeB :: RR a [b]
-> a
-> Black a b
-> Red Black a b
balLeB bl x (B y) = balance bl x (R y)
balRiB :: Black a b
-> a
-> RR a [b]
-> Red Black a b
balRiB (B y) = balance (R y)
balL :: RR a [b]
-> a
-> Red Black a b
-> RR a b
balL (R a) y c = R (C (B a), y, c)
balL (C t) x (R (B (a, y, b), z, c)) = R (C (B (t, x, a)), y, balLeB (C b) z c)
balL b x (C t) = C (balLeB b x t)
balR :: Red Black a b
-> a
-> RR a [b]
-> RR a b
balR a x (R b) = R (a, x, C (B b))
balR (R (a, x, B (b, y, c))) z (C d) = R (balRiB a x (C b), y, C (B (c, z, d)))
balR (C t) x b = C (balRiB t x b)
balance :: RR a [b]
-> a
-> RR a [b]
-> Red Black a b
balance (R a) y (R b) = R (B a, y, B b)
balance (C a) x b = balanceR a x b
balance a x (C b) = balanceL a x b
append :: Black a b
-> Black a b
-> Red Black a b
append (B (a, x, b)) (B (c, y, d)) = threeformB a x (appendR b c) y d
append _ _ = C E
threeformB :: Red Black a [b]
-> a
-> RR a [b]
-> a
-> Red Black a [b]
-> Red Black a b
threeformB a x (R (b, y, c)) z d = R (B (a, x, b), y, B (c, z, d))
threeformB a x (C b) y c = balLeB (C a) x (B (b, y, c))
appendR :: Red Black a b
-> Red Black a b
-> RR a b
appendR (C x) (C y) = C (append x y)
appendR (C t) (R (a, x, b)) = R (append t a, x, C b)
appendR (R (a, x, b)) (C t) = R (C a, x, append b t)
appendR (R (a, x, b)) (R (c, y, d)) = threeformR a x (append b c) y d
threeformR :: Black a b
-> a
-> Red Black a b
-> a
-> Black a b
-> RR a b
threeformR a x (R (b, y, c)) z d = R (R (a, x, b), y, R (c, z, d))
threeformR a x (C b) y c = R (R (a, x, b), y, C c)

131
RB4.hs Normal file
View File

@ -0,0 +1,131 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
module RedBlackTree where
data Nat = Zero | Succ Nat deriving (Eq, Ord, Show)
type One = Succ Zero
data RedBlack = Black | Red deriving (Eq, Ord, Show)
-- red-black trees are rooted at a black node
data RedBlackTree a = forall n. T (Node Black n a)
deriving instance Show a => Show (RedBlackTree a)
-- all paths from a node to a leaf have exactly n black nodes
data Node :: RedBlack -> Nat -> * -> * where
-- all leafs are black
Leaf :: Node Black One a
-- internal black nodes can have children of either color
B :: Node cL n a -> a -> Node cR n a -> Node Black (Succ n) a
-- internal red nodes can only have black children
R :: Node Black n a -> a -> Node Black n a -> Node Red n a
deriving instance Show a => Show (Node c n a)
-- one-hole context for red-black trees
data Context :: Nat -> RedBlack -> Nat -> * -> * where
-- if we're at the root, the hole is a black node
Root :: Context n Black n a
-- we can go left or right from a red node hole, creating a hole for a black node
BC :: Bool -> a -> Node Black n a -> Context m Red n a -> Context m Black n a
-- we can go left or right from a black node hole, creating a hole for either
EC :: Bool -> a -> Node cY n a -> Context m Black (Succ n) a -> Context m cX n a
data Zipper m a = forall c n. Zipper (Node c n a) (Context m c n a)
-- create a zipper
unZip :: Node Black n a -> Zipper n a
unZip = flip Zipper Root
-- destroy a zipper
zipUp :: Zipper m a -> Node Black m a
zipUp (Zipper x Root) = x
zipUp (Zipper x (BC goLeft a y c)) = zipUp $ Zipper (if goLeft then R x a y else R y a x) c
zipUp (Zipper x (EC goLeft a y c)) = zipUp $ Zipper (if goLeft then B x a y else B y a x) c
-- locate the node that should contain a in the red-black tree
zipTo :: Ord a => a -> Zipper n a -> Zipper n a
zipTo _ z@(Zipper Leaf _) = z
zipTo a z@(Zipper (R l a' r) c) = case compare a a' of
EQ -> z
LT -> zipTo a $ Zipper l (BC True a' r c)
GT -> zipTo a $ Zipper r (BC False a' l c)
zipTo a z@(Zipper (B l a' r) c) = case compare a a' of
EQ -> z
LT -> zipTo a $ Zipper l (EC True a' r c)
GT -> zipTo a $ Zipper r (EC False a' l c)
-- create a red-black tree
empty :: RedBlackTree a
empty = T Leaf
-- insert a node into a red-black tree
-- (see http://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Insertion)
insert :: Ord a => a -> RedBlackTree a -> RedBlackTree a
insert a t@(T root) = case zipTo a (unZip root) of
-- find matching leaf and replace with red node (pointing to two leaves)
Zipper Leaf c -> insertAt (R Leaf a Leaf) c
-- if it's already in the tree, there's no need to modify it
_ -> t
insertAt :: Node Red n a -> Context m c n a -> RedBlackTree a
-- 1) new node is root => paint it black and done
insertAt (R l a r) Root = T $ B l a r
-- 2) new node's parent is black => done
insertAt x (EC b a y c) = T . zipUp $ Zipper x (EC b a y c)
-- 3) uncle is red => paint parent/uncle black, g'parent red. recurse on g'parent
insertAt x (BC pb pa py (EC gb ga (R ul ua ur) gc)) = insertAt g gc
where p = if pb then B x pa py else B py pa x
u = B ul ua ur
g = if gb then R p ga u else R u ga p
-- 4) node is between parent and g'parent => inner rotation
insertAt (R l a r) (BC False pa py pc@(EC True _ _ _)) = insertAt (R py pa l) (BC True a r pc)
insertAt (R l a r) (BC True pa py pc@(EC False _ _ _)) = insertAt (R r pa py) (BC False a l pc)
-- 5) otherwise => outer rotation
-- XXX: GHC seems unable to infer that gy is Black so I have to do both cases
-- explicitly, rather than
-- insertAt x (BC True pa py (EC True ga gy gc)) =
-- T . zipUp $ Zipper (B x pa $ R py ga gy) gc
-- insertAt x (BC False pa py (EC False ga gy gc)) =
-- T . zipUp $ Zipper (B (R gy ga py) pa x) gc
insertAt x (BC True pa py (EC True ga gy@Leaf gc)) =
T . zipUp $ Zipper (B x pa $ R py ga gy) gc
insertAt x (BC True pa py (EC True ga gy@B {} gc)) =
T . zipUp $ Zipper (B x pa $ R py ga gy) gc
insertAt x (BC False pa py (EC False ga gy@Leaf gc)) =
T . zipUp $ Zipper (B (R gy ga py) pa x) gc
insertAt x (BC False pa py (EC False ga gy@B {} gc)) =
T . zipUp $ Zipper (B (R gy ga py) pa x) gc
-- can't derive, since we abstract over n, so we have to manually
-- check for identical structure
instance Eq a => Eq (RedBlackTree a) where
T Leaf == T Leaf =
True
T (B l@B {} a r@B {}) == T (B l'@B {} a' r'@B {}) =
a == a' && T l == T l' && T r == T r'
T (B (R ll la lr) a r@B {}) == T (B (R ll' la' lr') a' r'@B {}) =
a == a' && la == la' && T ll == T ll' && T lr == T lr' && T r == T r'
T (B l@B {} a (R rl ra rr)) == T (B l'@B {} a' (R rl' ra' rr')) =
a == a' && ra == ra' && T l == T l' && T rl == T rl' && T rr == T rr'
T (B (R ll la lr) a (R rl ra rr)) == T (B (R ll' la' lr') a' (R rl' ra' rr')) =
a == a' && la == la' && ra == ra' &&
T ll == T ll' && T lr == T lr' && T rl == T rl' && T rr == T rr'
_ == _ =
False
-- can't derive, since B abstracts over child node colors, so
-- manually check for identical structure
instance Eq a => Eq (Node c n a) where
Leaf == Leaf = True
R l a r == R l' a' r' = a == a' && l == l' && r == r'
b@B {} == b'@B {} = T b == T b'
_ == _ = False

85
RandList.hs Normal file
View File

@ -0,0 +1,85 @@
module RandList
( RandList
, empty
, isEmpty
, cons
, head
, tail
, lookup
, update
) where
import Prelude hiding (head, lookup, tail)
data BLT a = Leaf a
| Fork !Int (BLT a) (BLT a)
deriving (Eq, Show)
data Digit a = Zero
| One (BLT a)
deriving (Eq, Show)
type RandList a = [Digit a]
empty :: RandList a
empty = []
isEmpty :: RandList a -> Bool
isEmpty = null
cons :: a -> RandList a -> RandList a
cons x = insTree (Leaf x)
head :: RandList a -> a
head ts = x where (Leaf x, _) = borrowTree ts
tail :: RandList a -> RandList a
tail ts = ts' where (_, ts') = borrowTree ts
lookup :: RandList a -> Int -> a
lookup [] _ = error "Bad Index"
lookup (Zero : ts) i = lookup ts i
lookup (One t : ts) i
| i < size t = lookupTree t i
| otherwise = lookup ts (i - size t)
update :: RandList a -> Int -> a -> RandList a
update [] _ _ = error "Bad Index"
update (Zero : ts) i y = Zero : update ts i y
update (One t : ts) i y
| i < size t = One (updateTree t i y) : ts
| otherwise = One t : update ts (i - size t) y
-- Utility functions
size :: BLT a -> Int
size (Leaf _) = 1
size (Fork n _ _ ) = n
link :: BLT a -> BLT a -> BLT a
link t1 t2 = Fork (size t1 + size t2) t1 t2
insTree :: BLT a -> RandList a -> RandList a
insTree t [] = [One t]
insTree t (Zero : ts) = One t : ts
insTree t1 (One t2 : ts) = Zero : insTree (link t1 t2) ts
borrowTree :: RandList a -> (BLT a, RandList a)
borrowTree [One t] = (t, [])
borrowTree (One t : ts) = (t, Zero : ts)
borrowTree (Zero : ts) = (t1, One t2 : ts')
where (Fork _ t1 t2, ts') = borrowTree ts
lookupTree :: BLT a -> Int -> a
lookupTree (Leaf x) 0 = x
lookupTree (Leaf _) _ = error "Bad Index"
lookupTree (Fork n t1 t2) i
| i < (n `div` 2) = lookupTree t1 i
| otherwise = lookupTree t2 (i - n `div` 2)
updateTree :: BLT a -> Int -> a -> BLT a
updateTree (Leaf _) 0 y = Leaf y
updateTree (Leaf _) _ _ = error "Bad Index"
updateTree (Fork n t1 t2) i y
| i < (n `div` 2) = Fork n (updateTree t1 i y) t2
| otherwise = Fork n t1 (updateTree t2 (i - n `div` 2) y)

13
SkewNat.hs Normal file
View File

@ -0,0 +1,13 @@
module SkewNat where
type SkewNat = [Int] -- increasing list of powers of 2^{k+1}-1
inc :: SkewNat -> SkewNat
inc ws@(w1 : w2 : rest)
| w1 == w2 = 1 + w1 + w2 : rest
| otherwise = 1 : ws
inc ws = 1 : ws
dec :: SkewNat -> SkewNat
dec (1 : ws) = ws
dec (w : ws) = (w `div` 2) : (w `div` 2) : ws

61
SkewRandList.hs Normal file
View File

@ -0,0 +1,61 @@
module SkewRandList
( RList
, cons
, head
, tail
, lookup
, update ) where
import Prelude hiding (head, lookup, tail)
data BTree a = Leaf a
| Node a (BTree a) (BTree a)
deriving (Show, Eq)
data Digit a = Digit !Int (BTree a)
deriving (Show, Eq)
type RList a = [Digit a]
cons :: a -> RList a -> RList a
cons x (Digit w1 t1 : Digit w2 t2 : ts')
| w1 == w2 = Digit (1 + w1 + w2) (Node x t1 t2) : ts'
cons x ts = Digit 1 (Leaf x) : ts
head :: RList a -> a
head (Digit 1 (Leaf x) : _) = x
head (Digit _ (Node x _ _) : _) = x
tail :: RList a -> RList a
tail (Digit 1 (Leaf _) : ts) = ts
tail (Digit w (Node _ t1 t2) : ts) =
Digit w' t1 : Digit w' t2 : ts
where w' = w `div` 2
lookup :: RList a -> Int -> a
lookup (Digit w t : ts) i
| i < w = lookupTree w t i
| otherwise = lookup ts (i - w)
update :: RList a -> Int -> a -> RList a
update (Digit w t : ts) i y
| i < w = Digit w (updateTree w t i y) : ts
| otherwise = Digit w t : update ts (i-w) y
lookupTree :: Int -> BTree a -> Int -> a
lookupTree 1 (Leaf x) 0 = x
lookupTree _ (Node x _ _) 0 = x
lookupTree w (Node _ t1 t2) i
| i < w' = lookupTree w' t1 (i-1)
| otherwise = lookupTree w' t2 (i-1-w')
where w' = w `div` 2
updateTree :: Int -> BTree a -> Int -> a -> BTree a
updateTree 1 (Leaf _) 0 y = Leaf y
updateTree _ (Node _ t1 t2) 0 y = Node y t1 t2
updateTree w (Node x t1 t2) i y
| i < (w`div`2) =
Node x (updateTree w' t1 (i-1) y) t2
| otherwise =
Node x t1 (updateTree w' t2 (i-1-w') y)
where w' = w `div` 2

28
SparseNat.hs Normal file
View File

@ -0,0 +1,28 @@
module SparseNat where
type SparseNat = [Int] -- increasing list of powers of 2
carry :: Int -> SparseNat -> SparseNat
carry w [] = [w]
carry w ws@(w' : rest)
| w < w' = w : ws
| otherwise = carry (2 * w) rest
borrow :: Int -> SparseNat -> SparseNat
borrow w ws@(w' : rest)
| w < w' = rest
| otherwise = w : borrow (2 * w) ws
inc :: SparseNat -> SparseNat
inc = carry 1
dec :: SparseNat -> SparseNat
dec = borrow 1
add :: SparseNat -> SparseNat -> SparseNat
add ws [] = ws
add [] ws = ws
add m@(w1 : ws1) n@(w2 : ws2)
| w1 < w2 = w1 : add ws1 n
| w2 < w1 = w2 : add m ws2
| otherwise = carry (2 * w1) (add ws1 ws2)

30
StrictList.hs Normal file
View File

@ -0,0 +1,30 @@
module StrictList (
StrictList(..)
, foldl
, reverse
, head
, tail
) where
import Prelude hiding (foldl, head, reverse, tail)
data StrictList a = !a :$ !(StrictList a) | Empty
deriving (Show, Eq)
infixr 5 :$
foldl :: (b -> a -> b) -> b -> StrictList a -> b
foldl f = lgo
where lgo z Empty = z
lgo z (x :$ xs) = let z' = f z x in z' `seq` lgo z' xs
reverse :: StrictList a -> StrictList a
reverse = foldl (flip (:$)) Empty
head :: StrictList a -> a
head (x :$ _ ) = x
head Empty = error "Empty StrictList has no head"
tail :: StrictList a -> StrictList a
tail (_ :$ xs) = xs
tail Empty = error "Empty StrictList has no tail"

51
Zipper.hs Normal file
View File

@ -0,0 +1,51 @@
module Zipper where
data Tree a = Item a
| Section [Tree a]
deriving (Show, Eq)
data Path a = Top
| Node [Tree a] (Path a) [Tree a]
deriving (Show, Eq)
data Location a = Loc (Tree a) (Path a)
deriving (Show, Eq)
goLeft :: Location a -> Location a
goLeft (Loc _ Top) = error "Can't go left of top"
goLeft (Loc t (Node (l:left) up right)) = Loc l (Node left up (t:right))
goLeft (Loc _ (Node [] _ _)) = error "Can't go left of first"
goRight :: Location a -> Location a
goRight (Loc _ Top) = error "Can't go right of top"
goRight (Loc t (Node left up (r:right))) = Loc r (Node (t:left) up right)
goRight _ = error "Can't go right of last"
goUp :: Location a -> Location a
goUp (Loc _ Top) = error "Can't go up from top"
goUp (Loc t (Node left up right)) = Loc (Section (reverse left ++ t:right)) up
goDown :: Location a -> Location a
goDown (Loc (Item _) _) = error "Can't go down from item"
goDown (Loc (Section (t1:trees)) p) = Loc t1 (Node [] p trees)
nth :: Location a -> Int -> Location a
nth loc = go
where go 1 = goDown loc
go n | n > 0 = goRight (go (n-1))
| otherwise = error "nth expects a positive int"
replace :: Location a -> Tree a -> Location a
replace (Loc _ p) t = Loc t p
insertRight :: Location a -> Tree a -> Location a
insertRight (Loc _ Top) _ = error "Can't insert right of top"
insertRight (Loc t (Node left up right)) r = Loc t (Node left up (r:right))
insertLeft :: Location a -> Tree a -> Location a
insertLeft (Loc _ Top) _ = error "Can't insert left of top"
insertLeft (Loc t (Node left up right)) l = Loc t (Node (l:left) up right)
insertDown :: Location a -> Tree a -> Location a
insertDown (Loc (Item _) _) _ = error "Can't insert down of an item"
insertDown (Loc (Section sons) p) t1 = Loc t1 (Node [] p sons)