Skip to content

Instantly share code, notes, and snippets.

@moonmaster9000
Created May 2, 2010 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moonmaster9000/387489 to your computer and use it in GitHub Desktop.
Save moonmaster9000/387489 to your computer and use it in GitHub Desktop.
module Library
(Author,
Book,
AuthorIndex,
BookIndex,
Catalogued,
Catalog,
addAuthor,
addBook,
associate,
authors,
books,
catalogued
) where
import qualified Data.Map as Map
data Author = Author String deriving (Show, Eq, Ord)
data Book = Book String deriving (Show, Eq, Ord)
type AuthorIndex = Map.Map Author [Book]
type BookIndex = Map.Map Book [Author]
data Catalog =
Catalog {
authorIndex :: AuthorIndex,
bookIndex :: BookIndex
} deriving (Show)
-- class for determining if a book or author is
-- in the catalog
class Catalogued a where
catalogued :: a -> Catalog -> Bool
-- ********************************
-- API (exported) methods
-- ********************************
addAuthor :: Author -> Catalog -> Catalog
addAuthor a c@(Catalog as bs) =
c { authorIndex = insertUnlessPresent a [] as }
addBook :: Book -> Catalog -> Catalog
addBook b c@(Catalog as bs) =
c { bookIndex = insertUnlessPresent b [] bs }
-- associate an author "a" with a book "b"
-- this will update both the book and author
-- indexes in a given catalog
associate :: Author -> Book -> Catalog -> Catalog
associate a b (Catalog as bs) = Catalog as' bs'
where
as' = Map.alter (addValue b) a as
bs' = Map.alter (addValue a) b bs
addValue x Nothing = Just [x]
addValue x (Just ys) = Just (x:ys)
-- Return all the authors for a book as listed in a catalog
authors :: Book -> Catalog -> Maybe [Author]
authors b c = Map.lookup b (bookIndex c)
-- return all the books written by an author as listed in a catalog
books :: Author -> Catalog -> Maybe [Book]
books a c = Map.lookup a (authorIndex c)
-- returns True if an author or book is in
-- the given catalog
instance Catalogued Author where
catalogued a c = a `Map.member` (authorIndex c)
instance Catalogued Book where
catalogued b c = b `Map.member` (bookIndex c)
-- ********************************
-- private (unexported) methods
-- ********************************
insertUnlessPresent k v m
| k `Map.member` m = m
| otherwise = Map.insert k v m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment