Haskell Type Family Examples
A type family is a type-level function that chooses a result type for each input type. The examples in this lesson show that idea in three different jobs.
A family picks the first component of a pair
First maps a pair type to its first component type. The first component of the pair is a number.
{-# LANGUAGE TypeFamilies #-}
type family First p where
First (a, b) = a
firstOf :: (a, b) -> First (a, b)
firstOf (x, _) = x
main :: IO ()
main = print (firstOf (3, "hi"))A family picks a function result type
Output maps Int to String and String to Int. A positive number gives a word, and a short string gives its length.
{-# LANGUAGE TypeFamilies #-}
type family Output a where
Output Int = String
Output String = Int
describe :: Int -> Output Int
describe n = if n > 0 then "positive" else "zero"
size :: String -> Output String
size s = length s
main :: IO ()
main = do
putStrLn (describe 5)
print (size "hi")A family picks a transformation result type
Neg maps each input type to its own result type. Negating a number and negating a boolean give different kinds of results.
{-# LANGUAGE TypeFamilies #-}
type family Neg a where
Neg Int = Int
Neg Bool = Bool
negInt :: Int -> Neg Int
negInt x = -x
negBool :: Bool -> Neg Bool
negBool b = not b
main :: IO ()
main = do
print (negInt 4)
print (negBool True)Example
{-# LANGUAGE TypeFamilies #-}
type family First p where
First (a, b) = a
type family Output a where
Output Int = String
Output String = Int
type family Neg a where
Neg Int = Int
Neg Bool = Bool
firstOf :: (a, b) -> First (a, b)
firstOf (x, _) = x
describe :: Int -> Output Int
describe n = if n > 0 then "positive" else "zero"
negBool :: Bool -> Neg Bool
negBool b = not b
main :: IO ()
main = do
print (firstOf (8, "bye"))
putStrLn (describe 5)
print (negBool True)Key points
- Type family: a type-level function that maps one type to another.
- A type family can pick the first component of a pair type.
- A type family can pick the result type of a function from its input type.
- A type family can pick the result type of a transformation from its input type.
- One family handles one job, so each job gets its own family.
In this example, three families each handle one job. First picks a pair component, Output picks a function result, and Neg picks a transformation result. The prints show the pair component, the word for a positive number, and the negation of true.
Note
Each family in this lesson is closed, so its equations are fixed in one place.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
Which job can a type family do?