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

Haskell · Basic · question 5 of 100

How does Haskell handle errors and exceptions?

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

Haskell handles errors and exceptions through two primary mechanisms: ‘Maybe‘ and ‘Either‘ types for handling errors in a pure way, and the ‘IO‘ monad for handling exceptions in the context of impure computations.

Let’s discuss both mechanisms in more detail.

1. Error Handling using ‘Maybe‘ and ‘Either‘:

For pure computations that may fail or return a result, we can use the ‘Maybe‘ and ‘Either‘ types to express the possibility of failure explicitly in the type of the function.

‘Maybe a‘ type represents a computation that could result in a value of type ‘a‘ or a failure (represented by ‘Nothing‘). The ‘Maybe‘ type has two constructors:

- ‘Just a‘: Represents a successful computation with a result of type ‘a‘.

- ‘Nothing‘: Represents a failed computation.

Here is an example of using the ‘Maybe‘ type to handle errors in a safe division function:

safeDiv :: Float -> Float -> Maybe Float
safeDiv _ 0 = Nothing
safeDiv x y = Just (x / y)

‘Either a b‘ type represents a computation that could result in a value of type ‘b‘ on success, or an error of type ‘a‘ on failure. The ‘Either‘ type has two constructors:

- ‘Left a‘: Represents a failed computation with an error of type ‘a‘.

- ‘Right b‘: Represents a successful computation with a result of type ‘b‘.

Here’s an example of using the ‘Either‘ type to handle errors in a function that calculates the square root of a number:

safeSqrt :: Float -> Either String Float
safeSqrt x
  | x < 0     = Left "Cannot calculate square root of a negative number"
  | otherwise = Right (sqrt x)

2. Exception Handling using the ‘IO‘ monad:

For impure computations, Haskell provides the ‘IO‘ monad for dealing with exceptions, which uses the ‘Control.Exception‘ module to define a set of functions to throw, catch, and handle exceptions.

- Throwing exceptions: You can throw an exception using the ‘throwIO‘ function, which has the type ‘Exception e => e -> IO a‘. Here is an example of throwing an exception:

import Control.Exception

failOnNegative :: Float -> IO Float
failOnNegative x
  | x < 0     = throwIO (userError "Input must be non-negative")
  | otherwise = return x

- Catching exceptions: You can catch and handle exceptions using the ‘catch‘ function, which has the type ‘Exception e => IO a -> (e -> IO a) -> IO a‘. Here’s an example of catching an exception:

handleFailOnNegative :: Float -> IO Float
handleFailOnNegative x = failOnNegative x `catch` handler
  where
    handler :: IOError -> IO Float
    handler e = putStrLn ("Caught exception: " ++ show e) >> return 0

In summary, Haskell handles errors and exceptions using the ‘Maybe‘ and ‘Either‘ types for pure computations, and the ‘IO‘ monad for impure computations. By using these mechanisms, you can write code that makes the possible failures explicit in the types, making it easier to reason about and handle errors gracefully.

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