Haskell Functor Laws
The Functor laws are two rules that every correct Functor instance must follow. They are the identity law and the composition law.
The identity law holds for lists
fmap id should leave a list unchanged. The output True confirms the two lists match.
main :: IO ()
main = print (fmap id [1,2,3] == [1,2,3])The identity law holds for Maybe
fmap id should leave a Just value unchanged. The output True confirms the two values match.
main :: IO ()
main = print (fmap id (Just 7) == Just 7)The composition law holds for lists
One fmap with a composed function should match two fmaps in a row. The output True confirms the two results match.
main :: IO ()
main = print (fmap ((+1) . (*2)) [1,2,3] == fmap (+1) (fmap (*2) [1,2,3]))Example
main :: IO ()
main = do
print (fmap id (Just 5) == Just 5)
print (fmap ((*2) . (+3)) (Just 4) == fmap (*2) (fmap (+3) (Just 4)))Key points
- Identity law: fmap id gives back the same value unchanged.
- id: a function that returns its input unchanged.
- Composition law: mapping a composed function equals mapping the two functions one after another.
- Composition: the (.) operator joins two functions into one function.
- Law: a rule that an instance must satisfy for fmap to behave predictably.
In this example, both Functor laws are checked for a Just value. The first line checks the identity law. The second line checks the composition law with plus three followed by times two.
Note
a Functor instance that breaks a law can surprise code that uses fmap.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
Which equality states the identity law?