Lenses and Optics

Exactly one part of a product view (^.), set (.~), over (%~) One case of a sum type preview (^?), review (#) Zero or more parts over, toListOf (^..), traverseOf from, view, review Fold / Getter

A van Laarhoven lens is just type Lens s a = forall f. Functor f => (a -> f a) -> s -> f s, so lenses compose with plain ..

Libraries: lens (comprehensive), optics (better errors, opaque types), microlens (lightweight), generic-lens (lenses via Generics, #field labels). With OverloadedRecordDot, many simple read cases need no lenses at all.

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data Address = Address {_street :: String, _city :: String} deriving Show
data Person = Person {_name :: String, _age :: Int, _address :: Address} deriving Show
makeLenses ''Address                 -- generates lenses: street, city
makeLenses ''Person                  -- name, age, address

ana :: Person
ana = Person "Ana" 30 (Address "Main St" "Pune")

main :: IO ()
main = do
  print (ana ^. name)                          -- view: "Ana"
  print (ana ^. address . city)                -- compose lenses: "Pune"
  print (ana & age .~ 31)                      -- set
  print (ana & age %~ (+ 1))                   -- modify (over)
  print (ana & address . city .~ "Mumbai")     -- deep update without boilerplate
  print ([1, 2, 3] & traversed %~ (* 10))      -- [10,20,30]
  print ((1, 2) & _1 .~ "x")                   -- ("x",2)
  print (Just 5 ^? _Just)                      -- Just 5 (prisms for sum types)
  print (Left 3 ^? _Right :: Maybe Int)        -- Nothing
  print (toListOf (folded . _2) [(1, 'a'), (2, 'b')])   -- "ab"
  print (sumOf traversed [1, 2, 3])            -- 6
  print ([(1, "a"), (2, "b")] ^.. traversed . _2)        -
…