Slide 1

Slide 1 text

The Power Of Const Markus Hauck (@markus1189)

Slide 2

Slide 2 text

Introduction Functor Applicative Selective Conclusion Why This Talk • why a whole talk about Const? • one of the “funny” datatypes at first sight • not immediately obvious what it is good for • surprisingly, it is many useful usages • this talk shows (some of) them Markus Hauck (@markus1189) The Power Of Const 1

Slide 3

Slide 3 text

Introduction Functor Applicative Selective Conclusion newtype Const a b = Const { getConst :: a } Markus Hauck (@markus1189) The Power Of Const 2

Slide 4

Slide 4 text

Introduction Functor Applicative Selective Conclusion The Const Datatype 1 newtype Const a b = Const { getConst :: a } • two type parameters a and b • b is a phantom type • you can only ever get a value of type a out of it • type level version of the const function that ignores one of the two arguments: 1 const :: a -> b -> b 2 const x _ = x Markus Hauck (@markus1189) The Power Of Const 3

Slide 5

Slide 5 text

Introduction Functor Applicative Selective Conclusion The Rest Of This Talk • Functor instance • Applicative instance • Selective Applicative instance Markus Hauck (@markus1189) The Power Of Const 4

Slide 6

Slide 6 text

Introduction Functor Applicative Selective Conclusion Functor Markus Hauck (@markus1189) The Power Of Const 5

Slide 7

Slide 7 text

Introduction Functor Applicative Selective Conclusion The Functor Instance 1 instance Functor (Const a) where 2 fmap f c@(Const a) = _ 1 • Found hole: _ :: Const a b 2 ... 3 • Relevant bindings include 4 f :: a1 -> b 5 c :: Const a a1 6 a :: a Markus Hauck (@markus1189) The Power Of Const 6

Slide 8

Slide 8 text

Introduction Functor Applicative Selective Conclusion The Functor Instance 1 instance Functor (Const a) where 2 fmap _ (Const a) = Const a 1 ghci> c = Const @String @Int "can't touch me" 2 3 ghci> fmap (+1) c 4 Const "can't touch me" 5 6 ghci> fmap print c 7 Const "can't touch me" • unpack and retag (change the phantom type) • discards the function application • … but how is this useful? Markus Hauck (@markus1189) The Power Of Const 7

Slide 9

Slide 9 text

Introduction Functor Applicative Selective Conclusion Use of Const in Twan van Laarhoven Lenses 1 type Lens a b = forall f. Functor f => (b -> f b) -> a -> f a 2 _1 :: Lens (a, b) a 3 _1 f (x1, y) = fmap (\x2 -> (x2, y)) (f x1) • think: ’a’ somehow contains ’b’ • given: • functorial function modifying the b • and a “bigger” value of type a • produce new a that has the modified b “inside” Markus Hauck (@markus1189) The Power Of Const 8

Slide 10

Slide 10 text

Introduction Functor Applicative Selective Conclusion Implementing Getter With Const 1 type Lens a b = forall f. Functor f => (b -> f b) -> a -> f a 2 _1 :: Lens (a, b) a 3 _1 f (x1, y) = fmap (\x2 -> (x2, y)) (f x1) 4 5 get :: Lens a b -> a -> b 6 get l x = getConst (l Const x) 1 get _1 (42, 'a') 2 = getConst (_1 Const (42, 'a')) -- Def. of 'get' 3 = getConst (fmap (\x2 -> (x2, 'a')) (Const 42)) -- Def. of '_1' 4 = getConst (Const 42) -- Def. of 'fmap' for 'Const 5 = 42 -- The Answer! Markus Hauck (@markus1189) The Power Of Const 9

Slide 11

Slide 11 text

Introduction Functor Applicative Selective Conclusion Functor • first example: Functor for Const • useless at first glance • nice for lenses Markus Hauck (@markus1189) The Power Of Const 10

Slide 12

Slide 12 text

Introduction Functor Applicative Selective Conclusion Applicative Markus Hauck (@markus1189) The Power Of Const 11

Slide 13

Slide 13 text

Introduction Functor Applicative Selective Conclusion The Applicative Instance • probably one of my favorites • opens up a lot of possibilities • how? connects two very important concepts Markus Hauck (@markus1189) The Power Of Const 12

Slide 14

Slide 14 text

Introduction Functor Applicative Selective Conclusion The Applicative Instance 1 instance Applicative (Const m) where 2 pure :: a -> Const m a 3 pure = _pure 4 5 (<*>) :: Const m (a -> b) -> Const m a -> Const m b 6 Const f <*> Const v = _ap Markus Hauck (@markus1189) The Power Of Const 13

Slide 15

Slide 15 text

Introduction Functor Applicative Selective Conclusion The Applicative Instance 1 instance Monoid m => Applicative (Const m) where 2 pure :: a -> Const m a 3 pure _ = Const mempty 4 5 (<*>) :: Const m (a -> b) -> Const m a -> Const m b 6 Const f <*> Const v = Const (f <> v) Markus Hauck (@markus1189) The Power Of Const 14

Slide 16

Slide 16 text

Introduction Functor Applicative Selective Conclusion Using The Applicative Instance • but what does it mean? • we can use any function working with Applicatives and give them Monoids! Markus Hauck (@markus1189) The Power Of Const 15

Slide 17

Slide 17 text

Introduction Functor Applicative Selective Conclusion Using The Applicative Instance 1 traverse :: ... => (a -> Const m b) -> t a -> Const m (t b) 2 foldMap :: ... => (a -> m) -> t a -> m 1 • by using traverse with Const we get foldMap • that’s why Traversable is enough to define a Foldable instance Markus Hauck (@markus1189) The Power Of Const 16

Slide 18

Slide 18 text

Introduction Functor Applicative Selective Conclusion Using The Applicative Instance 1 traverse :: ... => (a -> Const m b) -> t a -> Const m (t b) 2 foldMap :: ... => (a -> m) -> t a -> m 1 • by using traverse with Const we get foldMap • that’s why Traversable is enough to define a Foldable instance 2 • Use Const to statically analyze Free Applicative programs • to accumulate monoidal value without performing actual effects Markus Hauck (@markus1189) The Power Of Const 16

Slide 19

Slide 19 text

Introduction Functor Applicative Selective Conclusion Using The Applicative Instance 1 traverse :: ... => (a -> Const m b) -> t a -> Const m (t b) 2 foldMap :: ... => (a -> m) -> t a -> m 1 • by using traverse with Const we get foldMap • that’s why Traversable is enough to define a Foldable instance 2 • Use Const to statically analyze Free Applicative programs • to accumulate monoidal value without performing actual effects 3 • Const highlights the relation between Applicative and Monoid • use everything from Monoids and use with functions that require Applicative • Applicative laws state that instances have to be monoidal in their effects Markus Hauck (@markus1189) The Power Of Const 16

Slide 20

Slide 20 text

Introduction Functor Applicative Selective Conclusion Selective Applicative Functors Markus Hauck (@markus1189) The Power Of Const 17

Slide 21

Slide 21 text

Introduction Functor Applicative Selective Conclusion https://www.staff.ncl.ac.uk/andrey.mokhov/selective-functors.pdf Markus Hauck (@markus1189) The Power Of Const 18

Slide 22

Slide 22 text

Introduction Functor Applicative Selective Conclusion This paper introduces an intermediate abstraction called selective applica- tive functors that requires all effects to be declared statically, but provides a way to select which of the effects to execute dynamically. • (emphasis mine) • Applicative: effects declared & executed statically • offer some of the benefits of Arrows, less powerful (not this talk :/) Markus Hauck (@markus1189) The Power Of Const 19

Slide 23

Slide 23 text

Introduction Functor Applicative Selective Conclusion Selective Functors 1 class Applicative f => Selective f where 2 select :: f (Either a b) -> f (a -> b) -> f b • (comes with some additional laws not shown here) • what does it buy me? • you can branch on Bools that are inside an “effect”1 1 ifS :: Selective f => f Bool -> f a -> f a -> f a 1“effect” with the usual caveats Markus Hauck (@markus1189) The Power Of Const 20

Slide 24

Slide 24 text

Introduction Functor Applicative Selective Conclusion The Selective Instance • now the interesting part: how does the instance for Const work? • with Selective we have two valid instances 1 newtype Over m a = Over { getOver :: m } 2 3 newtype Under m a = Under { getUnder :: m } • Over for static over-approximation • Under for static under-approximation Markus Hauck (@markus1189) The Power Of Const 21

Slide 25

Slide 25 text

Introduction Functor Applicative Selective Conclusion 1 -- Reminder: 2 class Applicative f => Selective f where 3 select :: f (Either a b) -> f (a -> b) -> f b 4 5 -- The two instances: 6 instance Monoid a => Selective (Over a) where 7 select (Over (Const c)) (Over (Const t)) = Over (Const (c <> t)) 8 9 instance Monoid a => Selective (Under a) where 10 select (Under (Const c)) _ = Under (Const c) • Over also goes into conditional branches • Under ignores conditionally executed parts Markus Hauck (@markus1189) The Power Of Const 22

Slide 26

Slide 26 text

Introduction Functor Applicative Selective Conclusion The Selective Instance • why is this so cool? • DSL using FreeSelective can express conditional branching and do static analysis/transformation on programs • Build systems à la carte (Mokhov, Andrey, Neil Mitchell, and Simon Peyton Jones.) • using Over and Under extremely useful to e.g. check properties of a program • does a certain effect always occur? Use Under • does a certain effect never occur: Use Over Markus Hauck (@markus1189) The Power Of Const 23

Slide 27

Slide 27 text

Introduction Functor Applicative Selective Conclusion Conclusion Markus Hauck (@markus1189) The Power Of Const 24

Slide 28

Slide 28 text

Introduction Functor Applicative Selective Conclusion Conclusion 1 newtype Const a b = Const { getConst :: a } • nonsense at first, but very useful • many instances that are very useful: • Functor • Applicative • Selective Applicative • Monad? (exercise) • good tool to understand monoidal aspects of Applicatives Markus Hauck (@markus1189) The Power Of Const 25

Slide 29

Slide 29 text

Introduction Functor Applicative Selective Conclusion Thanks! Markus Hauck (@markus1189) The Power Of Const 26

Slide 30

Slide 30 text

What Is Next? • we saw the instance for Applicative • important bridge between Monoid and Applicative • so what about the Monad instance? Markus Hauck (@markus1189) The Power Of Const 27

Slide 31

Slide 31 text

The Monad Instance? 1 import Data.Functor.Const 2 3 instance Monoid a => Monad (Const a) where 4 c@(Const x) >>= f = f _ 1 const-monad.hs:4:23: error: 2 • Found hole: _ :: Const a b 3 ... 4 • Relevant bindings include 5 f :: a1 -> Const a b (bound at const-monad.hs:4:19) 6 x :: a (bound at const-monad.hs:4:12) 7 c :: Const a a1 (bound at const-monad.hs:4:3) 8 ... Markus Hauck (@markus1189) The Power Of Const 28

Slide 32

Slide 32 text

• mempty would typecheck, but violate the left-identity law • we simply can’t “pretend” anymore • Const does not have a Monad instance, but still manages to teach us • somewhere between Applicative and Monad… Markus Hauck (@markus1189) The Power Of Const 29