import qualified Data.Map as Map

phoneBook :: [(String, String)]
phoneBook = 
    [("betty", "555-2938")
    ,("bonnie", "333-2928")
    ,("patsy", "222-2918")
    ,("penny", "111-2918")
    ]

-- 使用 type synonyms 可以实现

type PhoneBook = [(String, String)]

type PhoneNumber = String
type Name = String
type PhoneBook2 = [(Name, PhoneNumber)]

type AssocList k v = [(k,v)]

-- Either type example

data LockerState = Taken | Free deriving (Show, Eq)

type Code = String 

type LockerMap = Map.Map Int (LockerState, Code)

lockerLookup :: Int -> LockerMap -> Either String Code
lockerLookup lockerNumber map =
    case Map.lookup lockerNumber map of
        Nothing -> Left $ "Locker number " ++ show lockerNumber ++ " doesn't exist! "
        Just (state, code) -> if state /= Taken
                                then Right code 
                                else Left $ "Locker " ++ show lockerNumber ++ " is already taken! "

-- Nothing -> Left String 
-- Other -> 
--        Taken -> Left String 
--        Other -> Right Code

lockers :: LockerMap 
lockers = Map.fromList
    [(100, (Taken, "ZD39I"))
    ,(101, (Free, "JAH3I"))
    ,(103, (Free, "IQSA9"))
    ,(105, (Free, "QOTSA"))
    ,(109, (Taken, "893JX"))
    ,(110, (Taken, "98989"))
    ]


