Data structure slides and source code
This commit is contained in:
		
							
								
								
									
										22
									
								
								DenseNat.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								DenseNat.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										97
									
								
								HAMT.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										216
									
								
								HON.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										31
									
								
								Nested.hs
									
									
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										22
									
								
								Queue1.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Queue1.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										33
									
								
								Queue2.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										55
									
								
								Queue2.txt
									
									
									
									
									
										Normal 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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								RB1.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								RB1.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										179
									
								
								RB2.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										204
									
								
								RB3.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										131
									
								
								RB4.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										85
									
								
								RandList.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										13
									
								
								SkewNat.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										61
									
								
								SkewRandList.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										28
									
								
								SparseNat.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										30
									
								
								StrictList.hs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										51
									
								
								Zipper.hs
									
									
									
									
									
										Normal 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)
 | 
			
		||||
		Reference in New Issue
	
	Block a user