content: import Prelude hiding (lookup)
  
  {-- snippet MonadPlus --}
  class Monad m => MonadPlus m where
     mzero :: m a	
     mplus :: m a -> m a -> m a
  {-- /snippet MonadPlus --}
  
  {-- snippet instances --}
  instance MonadPlus [] where
     mzero = []
     mplus = (++)
  
  instance MonadPlus Maybe where
     mzero = Nothing
  
     Nothing `mplus` ys  = ys
     xs      `mplus` _ = xs
  {-- /snippet instances --}
  
  {-- snippet numbers --}
  data Context = Home | Mobile | Business
                 deriving (Eq, Show)
  
  type Phone = String
  
  albulena = [(Home, "+355-652-55512")]
  
  nils = [(Mobile, "+47-922-55-512"), (Business, "+47-922-12-121"),
          (Home, "+47-925-55-121"), (Business, "+47-922-25-551")]
  
  twalumba = [(Business, "+260-02-55-5121")]
  {-- /snippet numbers --}
  
  {-- snippet personalPhone --}
  onePersonalPhone :: [(Context, Phone)] -> Maybe Phone
  onePersonalPhone ps = case lookup Home ps of
                          Nothing -> lookup Mobile ps
                          Just n -> Just n
  {-- /snippet personalPhone --}
  
  {-- snippet businessPhones --}
  allBusinessPhones :: [(Context, Phone)] -> [Phone]
  allBusinessPhones ps = map snd numbers
      where numbers = case filter (contextIs Business) ps of
                        [] -> filter (contextIs Mobile) ps
                        ns -> ns
  
  contextIs a (b, _) = a == b
  {-- /snippet businessPhones --}
  
  {-- snippet caseless --}
  oneBusinessPhone :: [(Context, Phone)] -> Maybe Phone
  oneBusinessPhone ps = lookup Business ps `mplus` lookup Mobile ps
  
  allPersonalPhones :: [(Context, Phone)] -> [Phone]
  allPersonalPhones ps = map snd $ filter (contextIs Home) ps `mplus`
                                   filter (contextIs Mobile) ps
  {-- /snippet caseless --}
  
  {-- snippet lookup --}
  lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
  lookup _ []                      = Nothing
  lookup k ((x,y):xys) | x == k    = Just y
                       | otherwise = lookup k xys
  {-- /snippet lookup --}
  
  {-- snippet lookupM --}
  lookupM :: (MonadPlus m, Eq a) => a -> [(a, b)] -> m b
  lookupM _ []    = mzero
  lookupM k ((x,y):xys)
      | x == k    = return y `mplus` lookupM k xys
      | otherwise = lookupM k xys
  {-- /snippet lookupM --}
  