18

Click here to load reader

Monad presentation scala as a category

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Monad presentation   scala as a category

Category Theory

Theory and Applications for Functional Programming

Page 2: Monad presentation   scala as a category

Format of Talk1. Introduce definition from Category Theory2. Use something from Scala as an example3. Show it satisfies the definition.4. Do ^^ until Monad defined5. Prove that definition given in FP is equivalent to definition given in Category TheoryPlus random points about application and practicalities along the way

Page 3: Monad presentation   scala as a category

Note about foundations● Category Theory is itself a foundation of mathematics,

and strictly speaking you don’t need Set Theory to do Category Theory

● Nevertheless a lot of examples and language used to explain Category Theory is actually borrowed from Set Theory

● I will do the same as it makes things much easier

(strictly speaking I’m using the von Neumann–Bernays–Gödel (NBG) set theory Axiomatization, which is a conservative extension of ZFC that allows us to talk about Proper Classes (e.g. Class of all Sets)

Page 4: Monad presentation   scala as a category

Definition - Category1. a class ob(C) of objects2. a class hom(C) of morphisms, or arrows, or maps, between the objects. Each morphism f has a unique

source object a and target object b where a and b are in ob(C). We write f: a → b, and we say "f is a morphism from a to b".

3. for every three objects a, b and c, a binary operation hom(a, b) × hom(b, c) → hom(a, c) called composition of morphisms; the composition of f : a → b and g : b → c is written as g ∘ f or gf. (Some authors use

"diagrammatic order", writing f;g or fg.)

such that the following axioms hold:

a. (associativity) if f : a → b, g : b → c and h : c → d then h ∘ (g ∘ f) = (h ∘ g) ∘ f, and

b. (identity) for every object x, there exists a morphism 1x : x → x (some authors write idx) called the identity morphism for x, such

that for every morphism f : a → b, we have 1b ∘ f = f = f ∘ 1a.

Page 5: Monad presentation   scala as a category

Example - Scala SLet the set of Types in Scala be Ob(C)Let the set of 1 param Functions in Scala be hom(C)NOTATION: Methods of a Type A, that return a type B that take no params can be equivalently considered as 1 param functions f: A -> B. Therefore I will interchange method invocation and function application henceforth.Composition o is defined as simply normal function composition, nowFor any f, g, h (types obv) we have(h o (g o f))(x) = (g o f)(h(x)) = f(g(h(x))) = f((h o g)(x)) = ((h o g) o f)(x) - associativityFor any T, id_T : T -> T is defined by for any x is a T, id_T(x) = x, clearly this is an identity

Page 6: Monad presentation   scala as a category

Definition - Functor

Page 7: Monad presentation   scala as a category

Example - Parameterized TypesMany parameterized types in Scala can be viewed as Functors with their map operation;Let S be the Scala Category, and F: S -> S associate any T in Ob(S) to List[T] in Ob(S)associate any f: A -> B (for any A, B in Ob(S)) to map(f): List[A] -> List[B]. Now for any T in Ob(S)F(id_T)(someList) = someList.map(x => x) = (x => x)(someList) = id_List[T] = id_F[T]- so satisfies identity preservationAnd it’s obvious that someList.map(f).map(g) = someList.map(g o f), so satisfies composition preservation

Practical PointWhen you write a parameterized type in an API in Scala with a map function, you are telling the API user that map(f).map(g) is the same as map(f o g). So in Scalding, it’s often convenient to chain map operations together for readability, rather than compose the functions - but Scalding is clever, it will compose the functions for you so that your still O(N) not O(2N), O(3N) etc.

Page 8: Monad presentation   scala as a category

Definition - Natural Transformation

. If F and G are functors between the categories C and D, then a natural transformation η from F to G associates to every object X in C a morphism ηX : F(X) → G(X) between objects of D, called the component of η at X, such that for every morphism f : X → Y in C we have:

Page 9: Monad presentation   scala as a category

Example - FlattenLet F: S -> S and G: S -> S be the Option[Option[ _ ]] Functor and Option[ _ ] Functor respectively.NOTATION: will be sloppy henceforthLet f: X -> Y in Hom(S)So F(f): Option[Option[ X ]] -> Option[Option[ Y ] is .map(_.map(f))G(f): Option[X] -> Option[Y] is .map(f)

Page 10: Monad presentation   scala as a category

Example - Flatten - ContinuedLet N_x be .flatten[x], then flatten is a Natural Transformation:N_Y = flatten[Y]: Option[Option[Y]] -> Option[Y]N_X = flatten[X]: Option[Option[X]] -> Option[X]So N_Y o F(f) = .map(_.map(f)).flattenand G(f) o N_X = .flatten.map(f). NowSome(Some(x)).map(_.map(f)).flatten = Some(Some(x).map(f)).flatten = Some(Some(f(x)).flatten= Some(f(x)) = Some(x).map(f) = Some(Some(x)).flatten.map(f)

Note there are many more natural transformations, like if we defined toList on Option.Practical PointKnowing an operation is a natural transformation makes refactoring easier.

Page 11: Monad presentation   scala as a category

Definition - Monad!!

Page 12: Monad presentation   scala as a category

Example - Option MonadLet F be the Option Functor, then combined with the flatten natural transformation M we have a monad: For any X in Ob(S)F(M_X) = map(_.flatten) : Option[Option[Option[X]]] -> Option[Option[X]]M_F(X) = M_Option[X] = flatten[Option[X]]: Option[Option[Option[X]]] -> Option[Option[X]]soM_X o F(M_X) = .map(_.flatten).flatten : Option[Option[Option[X]]] -> Option[X]M_X o M_F(X) = .flatten.flatten : Option[Option[Option[X]]] -> Option[X]Let’s check these are equalSome(Some(Some(x))).map(_.flatten).flatten = Some(Some(Some(x)).flatten).flatten= Some(Some(x)).flatten = Some(x) = Some(Some(x)).flatten = Some(Some(Some(x))).flatten.flattenTherefore we have the first coherence condition ...

Page 13: Monad presentation   scala as a category

Example - Option Monad continuedNow our Identity natural transformation will be the Some function, i.e.N_X = Some: X -> Option[X] (which is the same as Id(X) -> Option[X])soF(N_X) = .map(Some), soM_X o F(N_X) = .map(Some).flatten, which is clearly the identity Functor (other way round - exercise)

Page 14: Monad presentation   scala as a category

Definition - Monad in FPIn functional programming a monadic Type M is simply defined in terms of flatMap, where:For any f: X -> M[Y], g: Y -> M[Z], and any x: M[X]x.flatMap(f).flatMap(g) = x.flatMap(f(_).flatMap(g))and there exists a neutral element N: X -> M[X], wherex.flatMap(N) = x

Page 15: Monad presentation   scala as a category

Theorem - EquivalenceThe two previous definitions are equivalent when we make the following substitution .map(f).flatten for flatMap(f) - (*)Proof:.flatten.flatten = .map(_.flatten).flatten - Monad Category Theory=> .map(f(_).map(g)).flatten.flatten = .map(f(_).map(g)).map(_.flatten).flatten - by substituting in .map(f(_).map(g))Now RHS = .map(f(_).map(g).flatten).flatten - by Functor Composition Preservation= .flatMap(f(_).map(g).flatten) - by (*)= .flatMap(f(_).flatMap(g)) - by (*)

...

Page 16: Monad presentation   scala as a category

Proof continuedNow LHS = x.map(f(_)).map(_.map(g)).flatten.flatten - by Functor Composition Preservation= x.map(f).flatten.map(g).flatten - since flatten is a natural transformation (recall earlier slide)= x.flatMap(f).flatMap(g) - by (*) twice.

Therefore.flatMap(f(_).flatMap(g)) = .flatMap(f).flatMap(g)

It remains to show the identity conditions (exercise)

Page 17: Monad presentation   scala as a category

Further ReadingMonoids - Used in Reduce operations in Map Reduce to parallelize operations that cumulate a single value. E.g. + is a monoid.

Covariance and Contravariance - Used in Typing rules for type inference

Page 18: Monad presentation   scala as a category

Summary of Applications1. Using Category Theoretic notions in code is a little like a formalization of design patterns2. When a reader sees a particular notion, they need to use less cognitive resources to comprehend the code by familiarity3. It’s easier to refactor code due to known equivalences, some of these equivalences are even used by Intellij (and ReSharper for LINQ) for the auto-refactor shortcuts4. Sometimes APIs allow the user to write readable code, but the resulting compiled code will be in it’s most computationally efficient representation.5. Compilers use concepts in Category Theory6. State hiding FP design