Abstract Nonsense for Functional Programmers - edsko.net

0 downloads 152 Views 216KB Size Report
Jan 9, 2009 - objects. C. X. Y. Z f g. Example: category Hask of Haskell types and programs. Edsko de Vries. Abstract No
Abstract Nonsense for Functional Programmers Edsko de Vries

January 9, 2009

Edsko de Vries

Abstract Nonsense for Functional Programmers

Introduction A category C consists of a set of objects and morphisms between objects.

C Y f

g

X

Z

Example: category Hask of Haskell types and programs.

Edsko de Vries

Abstract Nonsense for Functional Programmers

Functors A functor F is a morphism in the category Cat of categories.

F

D

C • •

• •



class Functor f :: * → * where fmap :: (a → b) → f a → f b

Edsko de Vries

Abstract Nonsense for Functional Programmers

Functor Laws In addition, a functor must satisfy a number of laws: I F (f

: A → B ) : F (A) → F (B )

I F (g

◦ f ) = Fg ◦ Ff = 1FA

I F ( 1A )

In Haskell: fmap (f :: a → b) :: f a → f b fmap (g . f) = fmap g . fmap f fmap id = id

Question: the functor laws are sufficient to guarantee that Cat is a category, but are they necessary?

Edsko de Vries

Abstract Nonsense for Functional Programmers

Hom Functors Pick a category C and an object A : C . Then Hom(A, −) : C → Set is a functor:

Set

C A→B

B Hom( A, −)

f

λg · f ◦ g A→C

C

A functor F is represented by an object A : C if F is naturally isomorphic to Hom(A, −).

Edsko de Vries

Abstract Nonsense for Functional Programmers

Algebras An algebra is a set A together with some operations that return values in that set. Examples: I I I

(N, 0 :: 1 → N, (+) :: N × N → N) (B, true :: 1 → B, (≡) :: B × B → B) (B, false :: 1 → B, (∨) :: B × B → B)

Alternatively: I I I

(N, in :: 1 + N × N → N) (B, in :: 1 + B × B → B) (B, in :: 1 + B × B → B)

Or, letting F X = 1 + X × X , I I I

(N, in :: F N → N) (B, in :: F B → B) (B, in :: F B → B) Edsko de Vries

Abstract Nonsense for Functional Programmers

Homomorphisms A homomorphism is a structure preserving map between F algebras: inA

FA −−−→ A

  yh

 

Fh y

FB −−−→ B inB

Take F X = 1 + X × X . Consider f : (N∗ , e, (++)) → (N, 0, (+)). in

1 + N∗ × N∗ −−−→   1+f ×f y

N∗   yf

f [] = 0 f ( xs ++ ys ) = f xs + f ys

1 + N × N −−−→ N in

Underspecified: both length and sum satisfy the equations. Edsko de Vries

Abstract Nonsense for Functional Programmers

Initial algebras However, when we take F X = 1 + N × X and then consider f : (N∗ , e, (:)) → (N, 0, (+)), we get in

1 + N × N∗ −−−→   1+N×f y

N∗   yf

1 + N × N −−−→ N in

In other words, f [] = 0 f (n: ns ) = n + f ns

(Inductive) datatypes correspond to initial algebras; the corresponding homomorphisms are called catamorphisms or folds.

Edsko de Vries

Abstract Nonsense for Functional Programmers

Monads A monad on a category C is defined to be a triple (T , η, µ) of a functor T : C → C and two natural transformation η : 1C → C and µ : T 2 → T :

T

ηT

1C In Haskell:

T2 µ



T3

T



T2 µ

µT

1C

T2

T

µ

T

class Monad (t :: * → *) where return :: ∀ a. a → t a join :: ∀ a. (t (t a )) → t a join . return = id = join . fmap return join . join = join . fmap join ( > >=) :: m a → (a → m b) → m b x >>= f = join ( fmap f x) Edsko de Vries

Abstract Nonsense for Functional Programmers

Partiality Monad (removed)

Edsko de Vries

Abstract Nonsense for Functional Programmers

Natural transformations A natural transformation η is a morphism in the functor category Fun(C , D) of functors between C and D .

D

C

F

X f

Ff FX

FY

ηX Y

G

GX

ηY Gf

GY

In Haskell: f :: X → Y F , G :: * → * η . fmap f = fmap f . η

(Theorem for free!)

Edsko de Vries

Abstract Nonsense for Functional Programmers

Yoneda Lemma Pick an object A in a category C , and let hA = Hom(A, −) Let F be an arbitrary functor from C to Set. Then

Lemma (Yoneda) Nat(hA , F ) ∼ = F (A) Naturality square for η : Nat(hA , F ): hA f

hA X −−−→ hA Y

  ηX y

  ηY y

FX −−−→ FY Ff

In Haskell: η :: ∀ b. (a → b) → f b Edsko de Vries

Abstract Nonsense for Functional Programmers

Witness (in Haskell) Recall

Lemma (Yoneda) Nat(hA , F ) ∼ = F (A) In Haskell: check :: Functor f ⇒ f a → ( ∀ b. (a → b) → f b) uncheck :: Functor f ⇒ ( ∀ b. (a → b) → f b) → f a

Edsko de Vries

Abstract Nonsense for Functional Programmers

Identity functor Lemma (Yoneda) The following functions are mutually inverse. check :: Functor f ⇒ f a → ( ∀ b. (a → b) → f b) uncheck :: Functor f ⇒ ( ∀ b. (a → b) → f b) → f a

Specific instance: take f = id. check :: a → ( ∀ b. (a → b) → b) check a f = f a uncheck :: ( ∀ b. (a → b) → b) → a uncheck t = ?

Edsko de Vries

Abstract Nonsense for Functional Programmers

List functor Lemma (Yoneda) The following functions are mutually inverse. check :: Functor f ⇒ f a → ( ∀ b. (a → b) → f b) uncheck :: Functor f ⇒ ( ∀ b. (a → b) → f b) → f a

Specific instance: take f = []. check :: [a] → ( ∀ b. (a → b) → [b ]) check f as = map f as uncheck :: ( ∀ b. (a → b) → [b ]) → [a] uncheck t = ?

Edsko de Vries

Abstract Nonsense for Functional Programmers

Hom functor Lemma (Yoneda) The following functions are mutually inverse. check :: Functor f ⇒ f a → ( ∀ b. (a → b) → f b) uncheck :: Functor f ⇒ ( ∀ b. (a → b) → f b) → f a

Specific instance: take f = Hom(C , −). check :: (c → a) → ( ∀ b. (a → b) → (c → b )) check a f = f . a uncheck :: ( ∀ b. (a → b) → (c → b )) → (c → a) uncheck t = ?

Edsko de Vries

Abstract Nonsense for Functional Programmers

General case Lemma (Yoneda) The following functions are mutually inverse. check :: Functor f ⇒ f a → ( ∀ b. (a → b) → f b) check a f = fmap f a uncheck :: Functor f ⇒ ( ∀ b. (a → b) → f b) → f a uncheck t = t id

Proof. check ( uncheck f) a = check (f id ) a = fmap a (f id ) = f ( fmap a id ) = f (a . id ) = f a

uncheck ( check f) = ( check f) id = fmap id f = id f = f

Edsko de Vries

Abstract Nonsense for Functional Programmers

Corollary Lemma (Barr and Wells, 4.5.4) If F : C → Set is represented by both C and D, then C ∼ = D. In other words, if the set of functions from C is isomorphic to the set of functions from D, then C and D are isomorphic. Justifies treating objects in a category as “black boxes”.

Edsko de Vries

Abstract Nonsense for Functional Programmers

References General category theory I “Category Theory”, Steve Awodey I “Category Theory for Computing Science” (3rd edition), Michael

Barr and Charles Wells Algebra I “Generic Programming—An Introduction”, Roland Backhouse et

al. Yoneda lemma in Haskell I “Reverse Engineering Machines with the Yoneda Lemma”, Dan

Piponi

Edsko de Vries

Abstract Nonsense for Functional Programmers