okasaki

Okasaki's Purely Functional Data Structures
Log | Files | Refs | LICENSE

commit 55af38a07988553ffc7709dafe75c3a852ed3523
Author: Jared Tobin <jared@jtobin.ca>
Date:   Wed, 19 Nov 2014 22:51:46 +1300

Initial commit.

Diffstat:
AStack.hs | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ATree.hs | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 0 deletions(-)

diff --git a/Stack.hs b/Stack.hs @@ -0,0 +1,63 @@ +{-# OPTIONS_GHC -Wall #-} + +module Stack where + +import Prelude hiding (head, tail) + +data Stack a = Nil | Cons a (Stack a) deriving (Eq, Show) + +instance Functor Stack where + fmap _ Nil = Nil + fmap f (Cons h t) = Cons (f h) (fmap f t) + +isEmpty :: Stack a -> Bool +isEmpty Nil = True +isEmpty _ = False + +empty :: Stack a +empty = Nil + +cons :: a -> Stack a -> Stack a +cons = Cons + +head :: Stack a -> Maybe a +head Nil = Nothing +head (Cons h _) = return h + +tail :: Stack a -> Maybe (Stack a) +tail Nil = Nothing +tail (Cons _ t) = return t + +fromList :: [a] -> Stack a +fromList = foldr Cons Nil + +toList :: Stack a -> [a] +toList Nil = [] +toList (Cons h t) = h : toList t + +append :: Stack a -> Maybe (Stack a) -> Maybe (Stack a) +append xs ys + | isEmpty xs = ys + | otherwise = do + h <- head xs + txs <- tail xs + t <- append txs ys + return (cons h t) + +update :: Stack a -> Int -> a -> Maybe (Stack a) +update Nil _ _ = Nothing +update (Cons h t) j y + | j < 0 = Nothing + | j == 0 = return (Cons y t) + | otherwise = do + nt <- update t (pred j) y + return (Cons h nt) + +-- exercise 2.1 +suffixes :: Stack a -> Stack (Stack a) +suffixes Nil = Nil +suffixes (Cons _ t) = Cons t (suffixes t) + +test :: Stack Int +test = fromList [1..10] + diff --git a/Tree.hs b/Tree.hs @@ -0,0 +1,114 @@ +{-# OPTIONS_GHC -Wall #-} + +module Tree where + +import Data.Maybe +import Prelude hiding (lookup) + +data Tree a = Leaf | Node (Tree a) a (Tree a) deriving (Eq, Show) + +empty :: Tree a +empty = Leaf + +insert :: Ord a => a -> Tree a -> Tree a +insert x Leaf = Node Leaf x Leaf +insert x t@(Node l e r) = case compare x e of + EQ -> t + LT -> Node (insert x l) e r + GT -> Node l e (insert x r) + +member :: Ord a => a -> Tree a -> Bool +member _ Leaf = False +member x (Node l e r) = case compare x e of + EQ -> True + LT -> member x l + GT -> member x r + +fromList :: Ord a => [a] -> Tree a +fromList = foldr insert empty + +test :: Tree Int +test = fromList [5..10] + +-- exercise 2.2 (max d + 1 comparisons) +altMember :: Ord a => a -> Tree a -> Bool +altMember x t = go t Nothing where + go (Node l e r) acc + | x < e = go l acc + | otherwise = go r (Just e) + go Leaf Nothing = False + go Leaf (Just e) = e == x + +-- exercise 2.3 (no unnecessary copying) +altInsert :: Ord a => a -> Tree a -> Tree a +altInsert x t = fromMaybe t (go t) where + go Leaf = return (Node Leaf x Leaf) + go (Node l e r) = case compare x e of + EQ -> Nothing + LT -> fmap (\alt -> Node alt e r) (go l) + GT -> fmap (\alt -> Node l e alt) (go r) + +-- exercise 2.4 (no unnecessary copying, max d + 1 comparisons) +efficientInsert :: Ord a => a -> Tree a -> Tree a +efficientInsert x t = fromMaybe t (go t Nothing) where + go (Node l e r) acc + | x < e = fmap (\alt -> Node alt e r) (go l acc) + | otherwise = fmap (\alt -> Node l e alt) (go r (Just e)) + go Leaf (Just e) + | e == x = Nothing + | otherwise = go Leaf Nothing + go Leaf Nothing = return (Node Leaf x Leaf) + +-- exercise 2.5a (balanced binary trees of depth n) +completeDepth :: Ord a => a -> Int -> Tree a +completeDepth x n + | n <= 0 = Leaf + | otherwise = + let t = completeDepth x (pred n) + in Node t x t + +-- exercise 2.5b (mostly-balanced binary trees of size n) +completeSize :: Ord a => a -> Int -> Tree a +completeSize x n + | n <= 0 = Leaf + | odd n = + let t = completeSize x (n `quot` 2) + in Node t x t + | otherwise = + let l = completeSize x (n `quot` 2) + r = completeSize x (n `quot` 2 - 1) + in Node l x r + +-- exercise 2.6 (finite map using tree) +newtype Bin k v = Bin (k, v) deriving Show + +instance Eq k => Eq (Bin k v) where + Bin (k0, _) == Bin (k1, _) = k0 == k1 + +instance Ord k => Ord (Bin k v) where + compare (Bin (k0, _)) (Bin (k1, _)) = compare k0 k1 + +newtype FiniteMap k v = FiniteMap (Tree (Bin k v)) deriving (Eq, Show) + +emptyMap :: FiniteMap k v +emptyMap = FiniteMap Leaf + +bind :: Ord k => k -> v -> FiniteMap k v -> FiniteMap k v +bind k v (FiniteMap m) = FiniteMap (insert' (Bin (k, v)) m) where + insert' x Leaf = Node Leaf x Leaf + insert' x (Node l e r) = case compare x e of + EQ -> Node l x r + LT -> Node (insert' x l) e r + GT -> Node l e (insert' x r) + +lookup :: Ord k => k -> FiniteMap k v -> Maybe v +lookup k (FiniteMap m) = lookup' m where + lookup' Leaf = Nothing + lookup' (Node l (Bin (key, v)) r) = case compare k key of + EQ -> Just v + LT -> lookup' l + GT -> lookup' r + +testMap :: FiniteMap Char Int +testMap = bind 'b' 2 (bind 'a' 1 emptyMap) +