content: {-# LANGUAGE TemplateHaskell #-}
  
  import Data.Label
  import Prelude hiding ((.), id)
  import Control.Category
  import Criterion.Main
  
  data Person = Person
    { _name   :: String
    , _age    :: Int
    , _place  :: Place
    , _birthplace :: Maybe Place
    } deriving (Show, Eq)
  
  data Place = Place
    { _city
    , _country
    , _continent :: String
    } deriving (Show, Eq)
  
  mkLabels [''Person, ''Place]
  
  jan :: Person
  jan = Person "Jan" 71 (Place "Utrecht" "The Netherlands" "Europe") Nothing
  
  getAge :: Int
  getAge = get age jan
  
  moveToAmsterdam :: Person -> Person
  moveToAmsterdam = set (city . place) "Amsterdam"
  
  moveToAmsterdam' :: Person -> Person
  moveToAmsterdam' person = person{_place = (_place person){_city = "Amsterdam"}}
  
  ageByOneYear :: Person -> Person
  ageByOneYear = modify age (+1)
  
  ageByOneYear' :: Person -> Person
  ageByOneYear' person = person{_age = (+1) $ _age person}
  
  moveAndAge :: Person -> Person
  moveAndAge = ageByOneYear . moveToAmsterdam . ageByOneYear . ageByOneYear . ageByOneYear
  
  moveAndAge' :: Person -> Person
  moveAndAge' = ageByOneYear' . moveToAmsterdam' . ageByOneYear' . ageByOneYear' . ageByOneYear'
  
  main :: IO ()
  main = 
    defaultMain
      [ bench "warmup" $ whnf show "Hello World"
      , bench "ageByOneYear" $ whnf ageByOneYear jan
      , bench "ageByOneYear'" $ whnf ageByOneYear' jan
      , bench "moveToAmsterdam" $ whnf moveToAmsterdam jan
      , bench "moveToAmsterdam'" $ whnf moveToAmsterdam' jan
      , bench "moveAndAge" $ whnf moveAndAge jan
      , bench "moveAndAge'" $ whnf moveAndAge' jan
      ]
  
  