Data vs Control

A tale of two functors

Arnaud Spiwack

Data and Control

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)

Data

Examples:

[a]
Map Int a

Data and Control

Data

Control

Data.Functor

Data.Traversable

Control.Applicative

Control.Monad

fmap
traverse

Control

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 and Control

Data

Control

Data.Functor

Data.Traversable

Control.Applicative

Control.Monad

fmap
traverse
pure, (<*>)
return, (>>=)

Yeaaah, but…

class Functor t

class Functor t => Traversable t

class Functor m => Applicative m

class Applicative m => Monad m

And, thinking about it…

Data examples:

[a]
Map Int a

Control examples:

Maybe a
IO a
[a]

Are lists Data or Control?

One last thing

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?

Ok, one last thing

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?

Ok ok, one last thing

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

A prism

forall p f . (Choice p, Applicative f) => p a (f b) -> p s (f t)

A prism

Linear types

{-# LANGUAGE LinearTypes #-}

f :: a ⊸ b
f x = … -- consumes x exactly once

Coming soon to a GHC near you

Linear types, by examples (1/3)

id x = x

linear

dup x = (x,x)

not linear

swap (x,y) = (y,x)

linear

forget x = ()

not linear

Linear types, by examples (2/3)

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

Linear types, by examples (3/3)

f x = dup x

linear

not linear

h u = u 0
g x = id (id x)
k u = u (u 0)

linear

not linear

What about map?

map f [] = []
map f (x:xs) = f x : map f xs
map :: (a ⊸ b) …
map :: (a ⊸ b) -> [a] …
map :: (a ⊸ b) -> [a] ⊸ [b]

Linear functors

class Functor t where
  fmap :: (a ⊸ b) -> t a ⊸ t b

Linear types and closures

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” notation

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

Linear monads

class Monad m where
  return :: a ⊸ m a
  (>>=) :: m a ⊸ (a ⊸ m b) ⊸ m b

Linear monads

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

Linear functors?

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

Linear functors!

Data vs Control: Functor

[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

Data vs Control: Applicatives

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

Data vs Control: Monads

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

Side note: comprehension

[ k x y z | x <- f, y <- g x, z <- h x y ]

comprehension = “do” notation

Is comprehension control?

Eugenio Moggi

Strong functors

(natural transformation)

A\otimes F(B) \longrightarrow F(A\otimes B)

(+ some laws)

str :: Functor f => a -> f b -> f (a, b)
str a fb = fmap (\b -> (a, b)) fb

Free variable

Conflation theorem

Theorem:

In Hask, all functors/monads are strong

Enriched categories

Theorem 1:

A symmetric monoidal closed category is enriched in itself.

Symmetric monoidal closed categories:

e.g. Hask, LinHask

Theorem 2:

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/

Made with Slides.com