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) -
…