{-# LANGUAGE AllowAmbiguousTypes #-} module Foo where import Control.Applicative data Currency class IsCurrency (a :: Currency) where data Money (currency :: Currency) where Money :: IsCurrency currency => Int -> Money currency data ExchangeRate from to convert :: IsCurrency to => ExchangeRate from to -> Money from -> Money to convert = undefined foo :: Maybe (Money to) -> Maybe (Money from) -> ExchangeRate from to -> Maybe (Money to) foo mMoneyTo mMoneyFrom exchangeRate = (fmap (convert exchangeRate) mMoneyFrom) <|> mMoneyTo