Slide 1

Slide 1 text

lens @markhibberd from the ground up

Slide 2

Slide 2 text

motivations

Slide 3

Slide 3 text

the ground up

Slide 4

Slide 4 text

data Lens a b = Lens { get :: a -> b , set :: b -> a -> a } intuitions

Slide 5

Slide 5 text

data Lens a b = Lens { get :: a -> b , set :: b -> a -> a } intuitions set-get ==> get l (set l b a) == b ! get-set ==> set l (get l a) a == a ! set-set ==> set l c (set l b a) == set l c a Pierce’s laws!

Slide 6

Slide 6 text

but… modify :: Lens a b -> (b -> b) -> a -> a modify l f a = set l (f (get l a)) a ! compose :: Lens a b -> Lens b c -> Lens a c compose l j = Lens (\a -> get j (get l a)) (\c a -> set l (set j c (get l a)) a)

Slide 7

Slide 7 text

but… modify :: Lens a b -> (b -> b) -> a -> a modify l f a = set l (f (get l a)) a ! compose :: Lens a b -> Lens b c -> Lens a c compose l j = Lens (\a -> get j (get l a)) (\c a -> set l (set j c (get l a)) a) efficiency matters!

Slide 8

Slide 8 text

but… data Wedge a = Wedge { _name :: String, _val :: a } ! name :: Lens (Wedge a) String name = Lens _name (\n w -> w { _name = n }) ! value :: Lens (Wedge a) a value = Lens _val (\v w -> w { _val = v })

Slide 9

Slide 9 text

but… data Wedge a = Wedge { _name :: String, _val :: a } ! name :: Lens (Wedge a) String name = Lens _name (\n w -> w { _name = n }) ! value :: Lens (Wedge a) a value = Lens _val (\v w -> w { _val = v }) polymorphic update matters

Slide 10

Slide 10 text

but… data Safety = Safety { _readOnly :: String } ! readOnly :: Lens Safety String readOnly = Lens _readOnly (error "don't do this")

Slide 11

Slide 11 text

but… read only / write only matters data Safety = Safety { _readOnly :: String } ! readOnly :: Lens Safety String readOnly = Lens _readOnly (error "don't do this")

Slide 12

Slide 12 text

but… (&&&) :: Lens a b -> Lens a c -> Lens a (b, c) (&&&) l j = Lens (\a -> (get l a, get j a)) (\(b, c) a -> set j c (set l b a))

Slide 13

Slide 13 text

but… (&&&) :: Lens a b -> Lens a c -> Lens a (b, c) (&&&) l j = Lens (\a -> (get l a, get j a)) (\(b, c) a -> set j c (set l b a)) not a lens

Slide 14

Slide 14 text

but… (&&&) :: Lens a b -> Lens a c -> Lens a (b, c) (&&&) l j = Lens (\a -> (get l a, get j a)) (\(b, c) a -> set j c (set l b a)) composition matters not a lens

Slide 15

Slide 15 text

but… data OneOf = First String | Second Int ! first :: Lens OneOf (Maybe String) first = undefined ! first :: Lens OneOf (Maybe String) first = undefined

Slide 16

Slide 16 text

but… data OneOf = First String | Second Int ! first :: Lens OneOf (Maybe String) first = undefined ! first :: Lens OneOf (Maybe String) first = undefined not a lens

Slide 17

Slide 17 text

but… data OneOf = First String | Second Int ! first :: Lens OneOf (Maybe String) first = undefined ! first :: Lens OneOf (Maybe String) first = undefined not a lens partiality matters

Slide 18

Slide 18 text

failed experiments data Store s a = Store (s -> a) s ! data Lens a b = Lens (a -> Store b a) ! ! ! ! ! ! ! !

Slide 19

Slide 19 text

failed experiments data Store s a = Store (s -> a) s ! data Lens a b = Lens (a -> Store b a) ! ! ! ! ! ! ! ! data Lens a b = Lens { get :: a -> b , set :: b -> a -> a }

Slide 20

Slide 20 text

failed experiments data Store s a = Store (s -> a) s ! data Lens a b = Lens (a -> Store b a) ! ! ! ! ! ! ! ! data Lens a b = Lens { get :: a -> b , set :: a -> b -> a }

Slide 21

Slide 21 text

failed experiments data Store s a = Store (s -> a) s ! data Lens a b = Lens (a -> Store b a) ! ! ! ! ! ! ! ! data Lens a b = Lens { run :: a ->(b ,b -> a) }

Slide 22

Slide 22 text

data Store s a = Store (s -> a) s ! data Lens a b = Lens (a -> Store b a) ! get :: Lens a b -> a -> b get (Lens l) a = case l a of Store _ s -> s ! set :: Lens a b -> b -> a -> a set (Lens l) b a = case l a of Store f _ -> f b failed experiments

Slide 23

Slide 23 text

data Store s a = Store (s -> a) s ! data Lens a b = Lens (a -> Store b a) ! get :: Lens a b -> a -> b get (Lens l) a = case l a of Store _ s -> s ! set :: Lens a b -> b -> a -> a set (Lens l) b a = case l a of Store f _ -> f b polymorphic update matters composition matters failed experiments partiality matters read only / write only matters

Slide 24

Slide 24 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board

Slide 25

Slide 25 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board ! set :: Lens’ a b -> b -> a -> a set = error “can we?” ! get :: Lens’ a b -> a -> b get = error “can we?”

Slide 26

Slide 26 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b a = let x = const $ Identity b -- :: b -> Identity b in undefined ! !

Slide 27

Slide 27 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b a = let x = const $ Identity b -- :: b -> Identity b y = l x -- :: a -> Identity a in runIdentity z !

Slide 28

Slide 28 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b a = let x = const $ Identity b -- :: b -> Identity b y = l x -- :: a -> Identity a z = y a -- :: Identity a in undefined

Slide 29

Slide 29 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b a = let x = const $ Identity b -- :: b -> Identity b y = l x -- :: a -> Identity a z = y a -- :: Identity a in runIdentity z

Slide 30

Slide 30 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b a = runIdentity (l (const $ Identity b) a) ! ! !

Slide 31

Slide 31 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b a = runIdentity . l (const $ Identity b) $ a ! ! !

Slide 32

Slide 32 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Identity a = Identity { runIdentity :: a } ! set :: Lens’ a b -> b -> a -> a set l b = runIdentity . l (const $ Identity b) ! ! !

Slide 33

Slide 33 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype ??? a = ??? ! get :: Lens’ a b -> a -> b get l a = undefined ! ! !

Slide 34

Slide 34 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = undefined ! ! !

Slide 35

Slide 35 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = undefined ! ! ! ! instance Functor (Const x) where fmap _ = Const . runConst

Slide 36

Slide 36 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = let x = Const -- :: b -> Const b b in undefined ! !

Slide 37

Slide 37 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = let x = Const -- :: b -> Const b b y = l x -- :: a -> Const b a in undefined !

Slide 38

Slide 38 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = let x = Const -- :: b -> Const b b y = l x -- :: a -> Const b a z = y a -- :: Const b a in undefined

Slide 39

Slide 39 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = let x = Const -- :: b -> Const b b y = l x -- :: a -> Const b a z = y a -- :: Const b a in runConst z

Slide 40

Slide 40 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = runConst (l Const a) ! ! !

Slide 41

Slide 41 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l a = runConst . l Const $ a ! ! !

Slide 42

Slide 42 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board newtype Const x a = Const x ! get :: Lens’ a b -> a -> b get l = runConst . l Const ! ! !

Slide 43

Slide 43 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board set :: Lens’ a b -> b -> a -> a set l b = runIdentity . l (const $ Identity b) ! get :: Lens’ a b -> a -> b get l = runConst . l Const ! ! ! !

Slide 44

Slide 44 text

! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a back to the drawing board set :: Lens’ a b -> b -> a -> a set l b = runIdentity . l (const $ Identity b) ! get :: Lens’ a b -> a -> b get l = runConst . l Const ! modify :: Lens’ a b -> (b -> b) -> a modify l f = runIdentity . l (Identity . f) !

Slide 45

Slide 45 text

functional elegance

Slide 46

Slide 46 text

composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a

Slide 47

Slide 47 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b y :: Lens b c x . y :: Lens a c ! ! ! ! !

Slide 48

Slide 48 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c x . y :: Lens a c ! ! ! ! !

Slide 49

Slide 49 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c ! ! ! ! !

Slide 50

Slide 50 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! ! ! ! !

Slide 51

Slide 51 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! ! !

Slide 52

Slide 52 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j !

Slide 53

Slide 53 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i !

Slide 54

Slide 54 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i i :: b -> f b

Slide 55

Slide 55 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i i :: b -> f b, j :: a -> f a

Slide 56

Slide 56 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i i :: b -> f b, j :: a -> f a, h :: c -> f c

Slide 57

Slide 57 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i i :: b -> f b, j :: a -> f a, h :: c -> f c x . y :: h -> j

Slide 58

Slide 58 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i i :: b -> f b, j :: a -> f a, h :: c -> f c x . y :: h -> j :: (c -> f c) -> (a -> f a)

Slide 59

Slide 59 text

function composition ! type Lens’ a b = forall f. Functor f => (b -> f b) -> a -> f a x :: Lens a b :: (b -> f b) -> (a -> f a) y :: Lens b c :: (c -> f c) -> (b -> f b) x . y :: Lens a c :: (c -> f c) -> (a -> f a) ! (.) :: (i -> j) -> (h -> i) -> h -> j ! x :: i -> j, y :: h -> i i :: b -> f b, j :: a -> f a, h :: c -> f c x . y :: h -> j :: (c -> f c) -> (a -> f a)

Slide 60

Slide 60 text

! type Lens a a’ b b’ = forall f. Functor f => (b -> f b’) -> a -> f a’ ! type Lens’ a b = Lens a a b b polymorphic update

Slide 61

Slide 61 text

! type Lens a a’ b b’ = forall f. Functor f => (b -> f b’) -> a -> f a’ ! type Simple f a b = f a a b b ! type Lens’ = Simple Lens polymorphic update

Slide 62

Slide 62 text

! type Lens a a’ b b’ = forall f. Functor f => (b -> f b’) -> a -> f a’ polymorphic update set :: Lens’ a b -> b -> a -> a set l b = runIdentity . l (const $ Identity b) ! get :: Lens’ a b -> a -> b get l = runConst . l Const ! modify :: Lens’ a b -> (b -> b) -> a modify l f = runIdentity . l (Identity . f) !

Slide 63

Slide 63 text

! type Lens a a’ b b’ = forall f. Functor f => (b -> f b’) -> a -> f a’ polymorphic update set :: Lens a a’ b b’ -> b’ -> a -> a’ set l b = runIdentity . l (const $ Identity b) ! get :: Lens a a’ b b’ -> a -> b’ get l = runConst . l Const ! modify :: Lens a a’ b b’ -> (b -> b’) -> a’ modify l f = runIdentity . l (Identity . f) !

Slide 64

Slide 64 text

! type Lens a a’ b b’ = forall f. Functor f => (b -> f b’) -> a -> f a’ polymorphic update set :: Lens a a’ b b’ -> b’ -> a -> a’ set l b = runIdentity . l (const $ Identity b) ! get :: Lens a a’ b b’ -> a -> b’ get l = runConst . l Const ! modify :: Lens a a’ b b’ -> (b -> b’) -> a’ modify l f = runIdentity . l (Identity . f) !

Slide 65

Slide 65 text

functional elegance even more

Slide 66

Slide 66 text

type Getter s a = forall r. (a -> Const r a) -> s -> Const r s ! type Setter s t a b = (a -> Identity b) -> s -> Identity t mirrored lenses

Slide 67

Slide 67 text

type Getter s a = forall r. (a -> Const r a) -> s -> Const r s ! type Setter s t a b = (a -> Identity b) -> s -> Identity t mirrored lenses lens . getter :: getter lens . setter :: setter getter . setter :: not a program

Slide 68

Slide 68 text

multiplate type Fold a b = forall f. (Contravariant f, Applicative f) => (b -> f b) -> a -> f a ! type Traversal a a’ b b’ = forall f. Applicative f => (b -> f b’) -> a -> f a’

Slide 69

Slide 69 text

multiplate type Fold a b = forall f. (Contravariant f, Applicative f) => (b -> f b) -> a -> f a ! type Traversal a a’ b b’ = forall f. Applicative f => (b -> f b’) -> a -> f a’ getter :: fold traversal :: fold lens :: traversal

Slide 70

Slide 70 text

type Traversal a a’ b b’ = forall f. Applicative f => (b -> f b’) -> a -> f a’ multiplate set :: Traversal a a’ b b’ -> b’ -> a -> a’ set l b = runIdentity . l (const $ Identity b) ! get :: Traversal a a’ b b’ -> a -> b’ get l = runConst . l Const ! modify :: Traversal a a’ b b’ -> (b -> b’) -> a’ modify l f = runIdentity . l (Identity . f) !

Slide 71

Slide 71 text

type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t) prisms / co-lens prism :: traversal traversal :: fold lens :: traversal

Slide 72

Slide 72 text

type Iso s t a b = forall p f. (Profunctor p, Functor f) => p a (f b) -> p s (f t) iso iso :: lens iso :: prism iso :: traversal iso :: getter iso :: setter

Slide 73

Slide 73 text

code

Slide 74

Slide 74 text

gotchas

Slide 75

Slide 75 text

references • Pierce’s original work on lenses / bidirectional programming: • http://www.cis.upenn.edu/~bcpierce/papers/index.shtml#Lenses • van Laarhoven’s original write-up: • http://www.twanvl.nl/blog/haskell/cps-functional-references • O’Connor’s coining of the term “van Laarhoven lens” and the insight into polymorphic update: • http://r6.ca/blog/20120623T104901Z.html • O’Connor’s multiplate paper (a.k.a. traversals): • http://arxiv.org/pdf/1103.2841v2.pdf • Kmett’s expanding on mirrored lens insights (a.k.a. read-only / write only): • http://comonad.com/reader/2012/mirrored-lenses/ • lens website, lots of links and video: • http://lens.github.io/ • git repo: • https://github.com/ekmett/lens • hackage: • http://hackage.haskell.org/package/lens

Slide 76

Slide 76 text

fin @markhibberd