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

Haskell · Expert · question 72 of 100

What is the role of "Phantom Types" in Haskell and what problems do they solve?

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

In Haskell, a "phantom type" is a type parameter that does not occur as part of the regular value constructor’s arguments. It is used for type-level annotations that can help us to express invariants or additional information about a data structure without actually affecting the runtime representation. Phantom types can thus enforce correct usage at the type level and help to catch certain types of errors at compile-time.

Let’s discuss the role of phantom types and the problems they solve with an example.

Suppose we have a simplified implementation of an units of measurement system, where we want to represent values with units like meters (m), seconds (s), and kilograms (kg):

data Meter
data Second
data Kilogram

data Quantity a = Quantity Double

Here, ‘Meter‘, ‘Second‘, and ‘Kilogram‘ are empty data types that act as units. The ‘Quantity‘ type is parameterized by a phantom type ‘a‘, which represents the type of the unit. The actual value of the quantity is stored as a ‘Double‘.

Now let’s define some functions to work with our units:

add :: Quantity a -> Quantity a -> Quantity a
add (Quantity x) (Quantity y) = Quantity (x + y)

subtract :: Quantity a -> Quantity a -> Quantity a
subtract (Quantity x) (Quantity y) = Quantity (x - y)

multiply :: Quantity a -> Double -> Quantity a
multiply (Quantity x) y = Quantity (x * y)

toMeters :: Double -> Quantity Meter
toMeters x = Quantity x

toSeconds :: Double -> Quantity Second
toSeconds x = Quantity x

toKilograms :: Double -> Quantity Kilogram
toKilograms x = Quantity x

Notice that the type signatures of our functions ‘add‘ and ‘subtract‘ ensure that we are only able to add or subtract between values of the same units:

> let x = toMeters 3
> let y = toSeconds 5
> let z = toMeters 2
>
> add x z    -- This works, both values are in meters
Quantity 5.0
>
> add x y    -- This doesn't compile, we're trying to add meters and seconds

The same goes for the function ‘multiply‘, which ensures that we can only multiply a quantity by a scalar value, preserving the unit:

> let mass = toKilograms 10
> multiply mass 4    -- This works, mass is in kilograms
Quantity 40.0

Phantom types can also be used to represent more complex type-level computations, for example, by making use of Haskell’s type-level programming features such as type families, and even expressing unit conversions.

In conclusion, phantom types serve as a way to extend the Haskell type system to enforce additional invariants or provide extra information, without affecting the runtime representation. They can help to prevent certain categories of bugs by catching them at compile-time and can be used to embed domain-specific knowledge within the type system.

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