Arnaud Spiwack
Data
Control
Data.Functor
Data.Traversable
Control.Applicative
Control.Monad
Data.Functor
Data.Traversable
“traverse is always the answer” is funny because of how surprisingly often that is true! — Matt Parsons
fmap :: (a -> b) -> t a -> t b
traverse
:: Applicative f => (a -> f b) -> t a -> f (t b)
Examples:
[a]
Map Int a
Data
Control
Data.Functor
Data.Traversable
Control.Applicative
Control.Monad
fmap
traverse
Control.Applicative
Control.Monad
pure :: a -> m a
(<*>) :: m (a -> b) -> m a -> m b
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
do
a <- tryA
b <- tryB a
c <- tryC a b
f c
“Do” notation
Examples:
Maybe a
IO a
Data
Control
Data.Functor
Data.Traversable
Control.Applicative
Control.Monad
fmap
traverse
pure, (<*>)
return, (>>=)
class Functor t
class Functor t => Traversable t
class Functor m => Applicative m
class Applicative m => Monad m
Data examples:
[a]
Map Int a
Control examples:
Maybe a
IO a
[a]
Are lists Data or Control?
instance Applicative [] where
pure x = [x]
fs <*> xs = [f x | f <- fs, x <- xs]
instance Applicative ZipList where
pure x = ZipList (repeat x)
(ZipList fs) <*> (ZipList ys) = ZipList (zipWith ($) fs xs)
Is Applicative Control, or Data, really?
data Lam a
= Var a
| App (Lam a) (Lam a)
| Abs (Lam (Maybe a))
instance Monad Lam
(>>=) :: Lam a -> (a -> Lam b) -> Lam b
Substitution!
Is Monad Control, or Data, really?
data V2 a = V2 a a
data V3 a = V3 a a a
instance Applicative V2
instance Traversable V2
instance Applicative V3
instance Traversable V3
sequenceA :: V3 (V2 a) -> V2 (V3 a)
V3 (V2 a)
Like ZipList
3x2 Matrix
Matrix transpose
forall p f . (Choice p, Applicative f) => p a (f b) -> p s (f t)
Photo by Michael Dziedzic on Unsplash
{-# LANGUAGE LinearTypes #-}
f :: a ⊸ b
f x = … -- consumes x exactly once
Coming soon to a GHC near you
id x = x
✓
linear
dup x = (x,x)
✗
not linear
swap (x,y) = (y,x)
✓
linear
forget x = ()
✗
not linear
f (Left x) = x
f (Right y) = y
✓
linear
✓
linear
✗
not linear
h x b = case b of
True -> x
False -> x
g z = case z of
Left x -> x
Right y -> y
k x b = case b of
True -> x
False -> ()
✓
linear
f x = dup x
✓
linear
✗
not linear
h u = u 0
g x = id (id x)
k u = u (u 0)
✓
linear
✗
not linear
map f [] = []
map f (x:xs) = f x : map f xs
map :: (a ⊸ b) …
map :: (a ⊸ b) -> [a] …
map :: (a ⊸ b) -> [a] ⊸ [b]
class Functor t where
fmap :: (a ⊸ b) -> t a ⊸ t b
f x = dup (\i -> (i, x))
✗
not linear
g x = id (\i -> (i, x))
✓
linear
Only a linearly consumed closure can have free linear variables
do
x <- f
y <- g x
z <- h x y
k x y z
f >>= \x ->
g x >>= \y ->
h x y >>= \z ->
k x y z
(>>=) :: m a ⊸ (a ⊸ m b) ⊸ m b
✓
(>>=) :: m a -> (a ⊸ m b) ⊸ m b
✗
Free linear variables in non-linear closures
(>>=) :: m a ⊸ (a ⊸ m b) -> m b
class Monad m where
return :: a ⊸ m a
(>>=) :: m a ⊸ (a ⊸ m b) ⊸ m b
class Monad m where
return :: a ⊸ m a
(>>=) :: m a ⊸ (a ⊸ m b) ⊸ m b
fmap :: (a ⊸ b) ⊸ m a ⊸ m b
fmap f x = x >>= (\a -> return (f a))
class Functor t where
fmap :: (a ⊸ b) -> t a ⊸ t b
class Functor m where
fmap :: (a ⊸ b) ⊸ m a ⊸ m b
class Data.Functor t where
fmap :: (a ⊸ b) -> t a ⊸ t b
class Control.Functor m where
fmap :: (a ⊸ b) ⊸ m a ⊸ m b
[a]
Maybe a
Map Int a
V2 a
V3 a
State s a
Writer w a
Reader e a
Lam a
class Data.Functor t where
fmap :: (a ⊸ b) -> t a ⊸ t b
class Control.Functor t where
fmap :: (a ⊸ b) ⊸ m a ⊸ m b
Data structures
Value wrapped in effects
class Data.Applicative t where
pure :: a -> t a
(<*>) :: t (a ⊸ b) ⊸ t a ⊸ t b
class Control.Applicative m where
pure :: a ⊸ m a
(<*>) :: m (a ⊸ b) ⊸ m a ⊸ m b
Zippable data structures
Static control flow
V2 a
V3 a
State s a
Writer w a
Reader e a
class Data.Monad t where
return :: a ⊸ t a
(>>=) :: t a ⊸ (a ⊸ t b) -> t b
class Control.Monad m where
return :: a ⊸ m a
(>>=) :: m a ⊸ (a ⊸ m b) ⊸ m b
Substitution
“Do” notation
State s a
Writer w a
Reader e a
[a]
Maybe a
Lam a
[ k x y z | x <- f, y <- g x, z <- h x y ]
comprehension = “do” notation
Is comprehension control?
Photo by Andrej Bauer via Wikimedia commons
(natural transformation)
(+ some laws)
str :: Functor f => a -> f b -> f (a, b)
str a fb = fmap (\b -> (a, b)) fb
Free variable
In Hask, all functors/monads are strong
A symmetric monoidal closed category is enriched in itself.
e.g. Hask, LinHask
In such a self-enriched category, strong functors/monads are the same as enriched functors/monads
https://slides.com/aspiwack/haskellove2020
https://github.com/tweag/linear-base/
https://www.tweag.io/blog/2020-01-16-data-vs-control/