content: {-# LANGUAGE OverloadedRecordDot #-}
  {-# LANGUAGE NoRebindableSyntax #-}
  
  module PprRecordDotSyntax2 where
  
  data Foo = Foo { foo :: Bar } deriving (Show, Eq)
  data Bar = Bar { bar :: Baz } deriving (Show, Eq)
  data Baz = Baz { baz :: Quux } deriving (Show, Eq)
  data Quux = Quux { quux :: Int } deriving (Show, Eq)
  
  main = do
    let a = Foo { foo = Bar{ bar = Baz { baz = Quux { quux = 42 } } } }
  
    -- A "selector" is an expression like '(.a)' or '(.a.b)'.
    putStrLn "-- selectors:"
    print $ (.foo) a  -- Bar { bar = Baz { baz = Quux { quux = 42 } } }
    print $ (.foo.bar) a -- Baz { baz = Quux { quux = 42 } }
    print $ (.foo.bar.baz) a -- Quux { quux = 42 }
    print $ (.foo.bar.baz.quux) a -- 42
  
    -- A "selection" is an expression like 'r.a' or '(f r).a.b'.
    putStrLn "-- selections:"
    print $ a.foo.bar.baz.quux -- 42
    print $ a.foo.bar.baz -- Quux { quux = 42 }
    print $ a.foo.bar -- Baz { baz = Quux { quux = 42 } }
    print $ a.foo -- Bar { bar = Baz { baz = Quux { quux = 42 } } }
  
    -- An "update" is an expression like 'r{ a.b = 12 }'.
    --
    -- We don't support these (in the case Rebindable Syntax is off) yet
    -- (waiting on HasField support).
    --
    -- Regular updates are fine though!
    print $ a{foo=(foo a){bar = (bar (foo a)){baz = (baz (bar (foo a))){quux = quux (baz (bar (foo a))) + 1}}}}
    print $ a{foo=(a.foo){bar = (a.foo.bar){baz = (a.foo.bar.baz){quux = a.foo.bar.baz.quux + 1}}}}
  