content: {-- snippet findCarrierBillingAddress --}
  import qualified Data.Map as M
  
  type PersonName = String
  type PhoneNumber = String
  type BillingAddress = String
  data MobileCarrier = Honest_Bobs_Phone_Network
                     | Morrisas_Marvelous_Mobiles
                     | Petes_Plutocratic_Phones
                       deriving (Eq, Ord)
  
  findCarrierBillingAddress :: PersonName
                            -> M.Map PersonName PhoneNumber
                            -> M.Map PhoneNumber MobileCarrier
                            -> M.Map MobileCarrier BillingAddress
                            -> Maybe BillingAddress
  {-- /snippet findCarrierBillingAddress --}
  findCarrierBillingAddress = undefined
  
  {-- snippet variation1 --}
  variation1 person phoneMap carrierMap addressMap =
      case M.lookup person phoneMap of
        Nothing -> Nothing
        Just number ->
            case M.lookup number carrierMap of
              Nothing -> Nothing
              Just carrier -> M.lookup carrier addressMap
  {-- /snippet variation1 --}
  
  {-- snippet variation2 --}
  variation2 person phoneMap carrierMap addressMap = do
    number <- M.lookup person phoneMap
    carrier <- M.lookup number carrierMap
    address <- M.lookup carrier addressMap
    return address
  {-- /snippet variation2 --}
  
  {-- snippet variation2a --}
  variation2a person phoneMap carrierMap addressMap = do
    number <- M.lookup person phoneMap
    carrier <- M.lookup number carrierMap
    M.lookup carrier addressMap
  {-- /snippet variation2a --}
  
  {-- snippet variation3 --}
  variation3 person phoneMap carrierMap addressMap =
      lookup phoneMap person >>= lookup carrierMap >>= lookup addressMap
    where lookup = flip M.lookup
  {-- /snippet variation3 --}
  