WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Haskell · Guru · question 98 of 100

Discuss a time when you used Haskell’s strong type system to solve a complex problem.?

📕 Buy this interview preparation book: 100 Haskell questions & answers — PDF + EPUB for $5

As a Haskell Programming expert, I remember working on a complex financial application where Haskell’s strong type system was crucial in preventing potential errors in the application logic. The problem was related to designing a small banking system that had to track different types of currencies and manage various financial operations like deposit, withdrawal, and currency conversion. We had to make sure that no erroneous currency conversions or invalid operations would occur.

First, let’s start by defining the data types for different currencies:

data Currency = USD | EUR | GBP
    deriving (Show, Eq)

Now let’s assume that each currency has a fixed conversion rate to other currencies. We can represent this as a function ‘convertCurrency‘:

convertCurrency :: Currency -> Currency -> Double -> Double
convertCurrency from to amount = case (from, to) of
    (USD, EUR) -> amount * 0.85
    (USD, GBP) -> amount * 0.75
    (EUR, USD) -> amount / 0.85
    (EUR, GBP) -> amount * 0.90
    (GBP, USD) -> amount / 0.75
    (GBP, EUR) -> amount / 0.90
    _           -> amount

The next step is to leverage Haskell’s strong type system and create separate data types for each supported currency. This will ensure that depositing, withdrawing, or converting currencies will be type-safe.

newtype Money a = Money { unMoney :: Double }
    deriving (Show, Eq, Num)

data USDTag
data EURTag
data GBPTag

type USD = Money USDTag
type EUR = Money EURTag
type GBP = Money GBPTag

usd :: Double -> USD
usd = Money

eur :: Double -> EUR
eur = Money

gbp :: Double -> GBP
gbp = Money

This way, we defined phantom types ‘USDTag‘, ‘EURTag‘, and ‘GBPTag‘, and then we created type synonyms ‘USD‘, ‘EUR‘, and ‘GBP‘ for the corresponding Money types.

Now let us redefine ‘convertCurrency‘ using these new types:

convertCurrency :: forall a b . (Money a -> Money b) -> Money a -> Money b
convertCurrency f = f

usdToEur :: Money USDTag -> Money EURTag
usdToEur (Money x) = Money $ x * 0.85

usdToGbp :: Money USDTag -> Money GBPTag
usdToGbp (Money x) = Money $ x * 0.75

-- Other conversion functions

With these data types in place, we can define some financial operations:

deposit :: Money a -> Money a -> Money a
deposit (Money x) (Money y) = Money (x + y)

withdraw :: Money a -> Money a -> Money a
withdraw (Money x) (Money y) = Money (x - y)

Here’s an example of usage:

main :: IO ()
main = do
    let usdAmount = usd 100
    let eurAmount = convertCurrency usdToEur usdAmount
    let gbpAmount = convertCurrency usdToGbp usdAmount

    putStrLn $ "100 USD in EUR: " ++ show eurAmount
    putStrLn $ "100 USD in GBP: " ++ show gbpAmount

    let newUsdAmount = deposit usdAmount (usd 50)
    putStrLn $ "Depositing 50 USD: " ++ show newUsdAmount

    let newGbpAmount = withdraw gbpAmount (gbp 20)
    putStrLn $ "Withdrawing 20 GBP: " ++ show newGbpAmount

By utilizing Haskell’s strong type system, we ensured that the application tracked currencies separately and avoided mixing them incorrectly or applying unsupported operations. Further, this type safety provided compile-time guarantees, preventing errors before runtime. This way, Haskell’s type system helped us solve a complex problem in a safe and expressive manner.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Haskell interview — then scores it.
📞 Practice Haskell — free 15 min
📕 Buy this interview preparation book: 100 Haskell questions & answers — PDF + EPUB for $5

All 100 Haskell questions · All topics