From 35eeaa4ea169b4de4b14159778e90415431aa693 Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Wed, 12 Dec 2012 11:09:15 +0100 Subject: [PATCH] added latest presentation blog post --- Rules | 11 +- content/css/main.sass | 58 +- .../en/blog/Category-Theory-Presentation.erb | 1000 ++++++++++++ .../fr/blog/Category-Theory-Presentation.erb | 1000 ++++++++++++ crash.log | 169 +- img_latest_blog_dir | 2 +- latest.ymd | 2 +- multi/blog/Category-Theory-Presentation.erb | 1001 ++++++++++++ output/Scratch/assets/css/main.css | 2 +- .../blog/Haskell-OpenGL-Mandelbrot/index.html | 4 + output/Scratch/en/blog/feed/feed.xml | 140 +- .../blog/Haskell-OpenGL-Mandelbrot/index.html | 4 + output/Scratch/fr/blog/feed/feed.xml | 137 +- output/Scratch/sitemap.xml | 1450 +++++++++-------- output/index.html | 6 +- output/keynote/categories.pdf | Bin 0 -> 13757697 bytes 16 files changed, 3965 insertions(+), 1021 deletions(-) create mode 100644 content/html/en/blog/Category-Theory-Presentation.erb create mode 100644 content/html/fr/blog/Category-Theory-Presentation.erb create mode 100644 multi/blog/Category-Theory-Presentation.erb create mode 100644 output/keynote/categories.pdf diff --git a/Rules b/Rules index 0e7e86a45..9b04e484d 100644 --- a/Rules +++ b/Rules @@ -46,17 +46,16 @@ compile '/html/*' do # item[:extension] returns 'html.erb' for multi-dotted filename ext = item[:extension].nil? ? nil : item[:extension].split('.').last - filter :ultraviolet # must be before kramdown - filter :graph - filter :description - filter :falacy - filter :blogimage - if ext == 'erb' filter :erb elsif ext == 'haml' || ext.nil? filter :haml elsif ext == 'md' || ext == 'markdown' + filter :ultraviolet # must be before kramdown + filter :graph + filter :description + filter :falacy + filter :blogimage filter :erb # I'll try not to use ruby anymore inside content filter :kramdown # filter :math_repair # after kramdown diff --git a/content/css/main.sass b/content/css/main.sass index d23392b1e..43e07e1c2 100644 --- a/content/css/main.sass +++ b/content/css/main.sass @@ -515,23 +515,16 @@ $hauteur_menu: 4em $contentMargin: 0em -.encadre, .black, .red, .intro, .resume, .shadow +.encadre, .black, .intro, .resume, .shadow padding: 2em margin: top: 2em bottom: 2em -.encadre, .black, .red, .shadow +.encadre, .black, .shadow +secondColor -pre .red - background: none - padding: 0 - margin: auto - border: none - box-shadow: none - .intro, .resume font-size: 0.9em +highlight @@ -600,6 +593,9 @@ figure text-align: center margin: .5em 0 +figure.left, figure.right + max-width: 30% + img.clean border: none background-color: none @@ -717,6 +713,11 @@ img background: none border: none +img.right + max-width: 30% + margin: + top: .6em + left: 2em img.left float: left max-width: 30% @@ -1070,3 +1071,42 @@ a.cut img max-width: 80% max-height: 6em + +section.slide + border-color: $borderColor + border: solid 1px + margin-bottom: 1em + padding: .5em + +.base03 + color: $base03 +.base02 + color: $base02 +.base01 + color: $base01 +.base00 + color: $base00 +.base0 + color: $base0 +.base1 + color: $base1 +.base2 + color: $base2 +.base3 + color: $base3 +.yellow + color: $yellow +.orange + color: $orange +.red + color: $red +.magenta + color: $magenta +.violet + color: $violet +.blue + color: $blue +.cyan + color: $cyan +.green + color: $green diff --git a/content/html/en/blog/Category-Theory-Presentation.erb b/content/html/en/blog/Category-Theory-Presentation.erb new file mode 100644 index 000000000..7fde2f554 --- /dev/null +++ b/content/html/en/blog/Category-Theory-Presentation.erb @@ -0,0 +1,1000 @@ +----- +isHidden: false +menupriority: 1 +kind: article +created_at: 2012-12-12T10:06:40+02:00 +title: Category Theory Presentation +author_name: Yann Esposito +author_uri: yannesposito.com +tags: + - category theory + - math + - functor +----- +Cateogry of Hask's endofunctors + +

Yesterday I was happy to make a presentation about Category Theory at Riviera Scala Clojure Meetup (note I used only Haskell for my examples).

+ + + +

If you don't want to read them through an HTML presentations framework or downloading a big PDF +just continue to read as a standard web page. +

+ +
+\(\newcommand{\F}{\mathbf{F}}\) +\(\newcommand{\E}{\mathbf{E}}\) +\(\newcommand{\C}{\mathcal{C}}\) +\(\newcommand{\D}{\mathcal{D}}\) +\(\newcommand{\id}{\mathrm{id}}\) +\(\newcommand{\ob}[1]{\mathrm{ob}(#1)}\) +\(\newcommand{\hom}[1]{\mathrm{hom}(#1)}\) +\(\newcommand{\Set}{\mathbf{Set}}\) +\(\newcommand{\Mon}{\mathbf{Mon}}\) +\(\newcommand{\Vec}{\mathbf{Vec}}\) +\(\newcommand{\Grp}{\mathbf{Grp}}\) +\(\newcommand{\Rng}{\mathbf{Rng}}\) +\(\newcommand{\ML}{\mathbf{ML}}\) +\(\newcommand{\Hask}{\mathbf{Hask}}\) +\(\newcommand{\Cat}{\mathbf{Cat}}\) +\(\newcommand{\fmap}{\mathtt{fmap}}\) +
+ +
+

Category Theory & Programming

+
for Rivieria Scala Clojure (Note this presentation uses Haskell)
+by Yann Esposito +
+ + @yogsototh, + + + +yogsototh + +
+
+
ENTER FULLSCREEN
+ HTML presentation: use arrows, space, swipe to navigate. +
+
+
+

Plan

+ +
+
+

Not really about: Cat & glory

+
+Cat n glory
credit to Tokuhiro Kawai (川井徳寛)
+
+ + + +
+
+

General Overview

+
+Samuel Eilenberg Saunders Mac Lane +
+ +

Recent Math Field
1942-45, Samuel Eilenberg & Saunders Mac Lane

+

Certainly one of the more abstract branches of math

+ +

+★: When is one thing equal to some other thing?, Barry Mazur, 2007
☆: Physics, Topology, Logic and Computation: A Rosetta Stone, John C. Baez, Mike Stay, 2009 +

+ + +
+
+

From a Programmer perspective

+
+

Category Theory is a new language/framework for Math

+
+ +
+
+

Math Programming relation

+Buddha Fractal +

Programming is doing Math

+

Strong relations between type theory and category theory.

+

Not convinced?
Certainly a vocabulary problem.

+

One of the goal of Category Theory is to create a homogeneous vocabulary between different disciplines.

+
+
+

Vocabulary

+mind blown +

Math vocabulary used in this presentation:

+
+

Category, Morphism, Associativity, Preorder, Functor, Endofunctor, Categorial property, Commutative diagram, Isomorph, Initial, Dual, Monoid, Natural transformation, Monad, Klesli arrows, κατα-morphism, ...

+
+
+
+

Programmer Translation

+lolcat + + + + + + + + +
+Mathematician + +Programmer +
+Morphism + +Arrow +
+Monoid + +String-like +
+Preorder + +Acyclic graph +
+Isomorph + +The same +
+Natural transformation + +rearrangement function +
+Funny Category + +LOLCat +
+ + +
+
+

Plan

+ +
+
+

Category

+ +

A way of representing things and ways to go between things.

+ +

A Category \(\mathcal{C}\) is defined by:

+ +
+
+

Category: Objects

+ +objects + +

\(\ob{\mathcal{C}}\) is a collection

+
+
+

Category: Morphisms

+ +morphisms + +

\(A\) and \(B\) objects of \(\C\)
+\(\hom{A,B}\) is a collection of morphisms
+\(f:A→B\) denote the fact \(f\) belongs to \(\hom{A,B}\)

+

\(\hom{\C}\) the collection of all morphisms of \(\C\)

+
+
+

Category: Composition

+

Composition (∘): associate to each couple \(f:A→B, g:B→C\) + $$g∘f:A\rightarrow C$$ +

+composition +
+
+

Category laws: neutral element

+

for each object \(X\), there is an \(\id_X:X→X\),
+such that for each \(f:A→B\):

+identity +
+
+

Category laws: Associativity

+

Composition is associative:

+associative composition +
+
+

Commutative diagrams

+ +

Two path with the same source and destination are equal.

+
+ Commutative Diagram (Associativity) +
+ \((h∘g)∘f = h∘(g∘f) \) +
+
+
+ Commutative Diagram (Identity law) +
+ \(id_B∘f = f = f∘id_A \) +
+
+
+
+

Question Time!

+ +
+ +
+- French-only joke - +
+
+
+
+

Can this be a category?

+

\(\ob{\C},\hom{\C}\) fixed, is there a valid ∘?

+
+ Category example 1 +
+ YES +
+
+
+ Category example 2 +
+ no candidate for \(g∘f\) +
NO +
+
+
+ Category example 3 +
+ YES +
+
+
+
+

Can this be a category?

+
+ Category example 4 +
+ no candidate for \(f:C→B\) +
NO +
+
+
+ Category example 5 +
+ \((h∘g)∘f=\id_B∘f=f\)
+ \(h∘(g∘f)=h∘\id_A=h\)
+ but \(h≠f\)
+ NO +
+
+
+
+

Categories Examples

+ +
+Basket of cats +
+- Basket of Cats - +
+
+
+
+

Category \(\Set\)

+ + + + +
+
+

Categories Everywhere?

+Cats everywhere + +
+
+

Smaller Examples

+ +

Strings

+Monoids are one object categories + + +
+
+

Finite Example?

+ +

Graph

+
+Each graph is a category +
+ + +
+
+

Number construction

+ +

Each Numbers as a whole category

+Each number as a category +
+
+

Degenerated Categories: Monoids

+ +Monoids are one object categories +

Each Monoid \((M,e,⊙): \ob{M}=\{∙\},\hom{M}=M,\circ = ⊙\)

+

Only one object.

+

Examples:

+ +
+
+

Degenerated Categories: Preorders \((P,≤)\)

+ + + +

At most one morphism between two objects.

+ +preorder category +
+
+

Degenerated Categories: Discrete Categories

+ +Any set can be a category +

Any Set

+

Any set \(E: \ob{E}=E, \hom{x,y}=\{x\} ⇔ x=y \)

+

Only identities

+
+
+

Choice

+

The same object can be seen in many different way as a category.

+

You can choose what are object, morphisms and composition.

+

ex: Str and discrete(Σ*)

+
+
+

Categorical Properties

+ +

Any property which can be expressed in term of category, objects, morphism and composition.

+ + +
+
+

Isomorph

+

isomorph cats isomorphism: \(f:A→B\) which can be "undone" i.e.
\(∃g:B→A\), \(g∘f=id_A\) & \(f∘g=id_B\)
in this case, \(A\) & \(B\) are isomorphic.

+

A≌B means A and B are essentially the same.
In Category Theory, = is in fact mostly .
For example in commutative diagrams.

+
+
+

Functor

+ +

A functor is a mapping between two categories. +Let \(\C\) and \(\D\) be two categories. +A functor \(\F\) from \(\C\) to \(\D\):

+ +
+
+

Functor Example (ob → ob)

+ +Functor +
+
+

Functor Example (hom → hom)

+ +Functor +
+
+

Functor Example

+ +Functor +
+
+

Endofunctors

+ +

An endofunctor for \(\C\) is a functor \(F:\C→\C\).

+Endofunctor +
+
+

Category of Categories

+ + + +

Categories and functors form a category: \(\Cat\)

+ +
+
+

Plan

+ +
+
+

Hask

+ +

Category \(\Hask\):

+ +Haskell Category Representation + + + +

Forget glitches because of undefined.

+
+
+

Haskell Kinds

+

In Haskell some types can take type variable(s). Typically: [a].

+

Types have kinds; The kind is to type what type is to function. Kind are the types for types (so meta).

+
Int, Char :: *
+[], Maybe :: * -> *
+(,), (->) :: * -> * -> *
+[Int], Maybe Char, Maybe [Int] :: *
+
+
+

Haskell Types

+

Sometimes, the type determine a lot about the function:

+
fst :: (a,b) -> a -- Only one choice
+snd :: (a,b) -> b -- Only one choice
+f :: a -> [a]     -- Many choices
+-- Possibilities: f x=[], or [x], or [x,x] or [x,...,x]
+
+? :: [a] -> [a] -- Many choices
+-- can only rearrange: duplicate/remove/reorder elements
+-- for example: the type of addOne isn't [a] -> [a]
+addOne l = map (+1) l
+-- The (+1) force 'a' to be a Num.
+ +

+

★:Theorems for free!, Philip Wadler, 1989

+
+
+

Haskell Functor vs \(\Hask\) Functor

+ +

A Haskell Functor is a type F :: * -> * which belong to the type class Functor ; thus instantiate +fmap :: (a -> b) -> (F a -> F b). + +

& F: \(\ob{\Hask}→\ob{\Hask}\)
& fmap: \(\hom{\Hask}→\hom{\Hask}\) + +

The couple (F,fmap) is a \(\Hask\)'s functor if for any x :: F a:

+ +
+
+

Haskell Functors Example: Maybe

+ +
data Maybe a = Just a | Nothing
+instance Functor Maybe where
+    fmap :: (a -> b) -> (Maybe a -> Maybe b)
+    fmap f (Just a) = Just (f a)
+    fmap f Nothing = Nothing
+
fmap (+1) (Just 1) == Just 2
+fmap (+1) Nothing  == Nothing
+fmap head (Just [1,2,3]) == Just 1
+
+
+

Haskell Functors Example: List

+ +
instance Functor ([]) where
+	fmap :: (a -> b) -> [a] -> [b]
+	fmap = map
+
fmap (+1) [1,2,3]           == [2,3,4]
+fmap (+1) []                == []
+fmap head [[1,2,3],[4,5,6]] == [1,4]
+
+
+

Haskell Functors for the programmer

+

Functor is a type class used for types that can be mapped over.

+ +
+
+

Haskell Functor intuition

+ +

Put normal function inside a container. Ex: list, trees...

+ +Haskell Functor as a box play +

+
+

Haskell Functor properties

+ +

Haskell Functors are:

+ + +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

"Non Haskell" Hask's Functors

+

A simple basic example is the \(id_\Hask\) functor. It simply cannot be expressed as a couple (F,fmap) where

+ +

Another example:

+ +
+
+

Also Functor inside \(\Hask\)

+

\(\mathtt{[a]}∈\ob{\Hask}\) but is also a category. Idem for Int.

+

length is a Functor from the category [a] to the cateogry Int:

+ +

+ +
+ +
+
+

Category of \(\Hask\) Endofunctors

+Category of Hask endofunctors +
+
+

Category of Functors

+

If \(\C\) is small (\(\hom{\C}\) is a set). All functors from \(\C\) to some category \(\D\) form the category \(\mathrm{Func}(\C,\D)\).

+ +

\(\mathrm{Func}(\C,\C)\) is the category of endofunctors of \(\C\).

+
+
+

Natural Transformations

+

Let \(F\) and \(G\) be two functors from \(\C\) to \(\D\).

+

Natural transformation commutative diagram A natural transformation: familly η ; \(η_X\in\hom{\D}\) for \(X\in\ob{\C}\) s.t.

+

ex: between Haskell functors; F a -> G a
Rearragement functions only.

+
+
+

Natural Transformation Examples (1/4)

+
data Tree a = Empty | Node a [Tree a]
+toTree :: [a] -> Tree a
+toTree [] = Empty
+toTree (x:xs) = Node x [toTree xs]
+ +

toTree is a natural transformation. It is also a morphism from [] to Tree in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram +
+ + +
+
+

Natural Transformation Examples (2/4)

+
data Tree a = Empty | Node a [Tree a]
+toList :: Tree a -> [a]
+toList Empty = []
+toList (Node x l) = [x] ++ concat (map toList l)
+ +

toList is a natural transformation. It is also a morphism from Tree to [] in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram
toList . toTree = id & toTree . toList = id &
therefore [] & Tree are isomorph.
+
+ + +
+
+

Natural Transformation Examples (3/4)

+
toMaybe :: [a] -> Maybe a
+toMaybe [] = Nothing
+toMaybe (x:xs) = Just x
+ +

toMaybe is a natural transformation. It is also a morphism from [] to Maybe in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram +
+ + +
+
+

Natural Transformation Examples (4/4)

+
mToList :: Maybe a -> [a]
+mToList Nothing = []
+mToList Just x  = [x]
+ +

toMaybe is a natural transformation. It is also a morphism from [] to Maybe in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+relation between [] and Maybe
There is no isomorphism.
Hint: Bool lists longer than 1.
+
+ + +
+
+

Composition problem

+

The Problem; example with lists:

+
f x = [x]       ⇒ f 1 = [1]   ⇒ (f.f) 1 = [[1]] ✗
+g x = [x+1]     ⇒ g 1 = [2]   ⇒ (g.g) 1 = ERROR [2]+1 ✗
+h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h.h) 1 = ERROR [2,3]+1 ✗ 
+ +

The same problem with most f :: a -> F a functions and functor F.

+
+
+

Composition Fixable?

+

How to fix that? We want to construct an operator which is able to compose:

+

f :: a -> F b & g :: b -> F c.

+

More specifically we want to create an operator ◎ of type

+

◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)

+

Note: if F = I, ◎ = (.).

+
+
+

Fix Composition (1/2)

+

Goal, find: ◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)
f :: a -> F b, g :: b -> F c:

+ +
+
+

Fix Composition (2/2)

+

Goal, find: ◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)
f :: a -> F b, g :: b -> F c, f x :: F b:

+ +
+
+

Necessary laws

+

For ◎ to work like composition, we need join to hold the following properties:

+ +
+
+

Klesli composition

+

Now the composition works as expected. In Haskell ◎ is <=< in Control.Monad.

+

g <=< f = \x -> join ((fmap g) (f x))

+
f x = [x]       ⇒ f 1 = [1]   ⇒ (f <=< f) 1 = [1] ✓
+g x = [x+1]     ⇒ g 1 = [2]   ⇒ (g <=< g) 1 = [3] ✓
+h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h <=< h) 1 = [3,6,4,9] ✓
+ + +
+
+

We reinvented Monads!

+

A monad is a triplet (M,⊙,η) where

+ +

Satisfying

+ +
+
+

Compare with Monoid

+

A Monoid is a triplet \((E,∙,e)\) s.t.

+ +

Satisfying

+ +
+
+

Monads are just Monoids

+
+

A Monad is just a monoid in the category of endofunctors, what's the problem?

+
+

The real sentence was:

+
+

All told, a monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor.

+
+
+
+

Example: List

+ +
-- In Haskell ⊙ is "join" in "Control.Monad"
+join :: [[a]] -> [a]
+join = concat
+
+-- In Haskell the "return" function (unfortunate name)
+η :: a -> [a]
+η x = [x]
+ + +
+
+

Example: List (law verification)

+

Example: List is a functor (join is ⊙)

+ +
join [ join [[x,y,...,z]] ] = join [[x,y,...,z]]
+                            = join (join [[[x,y,...,z]]])
+join (η [x]) = [x] = join [η x]
+ +

Therefore ([],join,η) is a monad.

+
+
+

Monads useful?

+

A LOT of monad tutorial on the net. Just one example; the State Monad

+

DrawScene to State Screen DrawScene ; still pure.

+
main = drawImage (width,height)
+
+drawImage :: Screen -> DrawScene
+drawImage screen = do
+    drawPoint p screen
+    drawCircle c screen
+    drawRectangle r screen
+
+drawPoint point screen = ...
+drawCircle circle screen = ...
+drawRectangle rectangle screen = ...
+
main = do
+    put (Screen 1024 768)
+    drawImage
+
+drawImage :: State Screen DrawScene
+drawImage = do
+    drawPoint p
+    drawCircle c
+    drawRectangle r
+
+drawPoint :: Point -> State Screen DrawScene
+drawPoint p = do
+    Screen width height <- get
+    ...
+
+
+

fold

+fold +
+
+

κατα-morphism

+catamorphism +
+
+

κατα-morphism: fold generalization

+

acc type of the "accumulator":
fold :: (acc -> a -> acc) -> acc -> [a] -> acc

+

Idea: put the accumulated value inside the type.

+
-- Equivalent to fold (+1) 0 "cata"
+(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' Nil))))
+(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' 0))))
+(Cons 'c' (Cons 'a' (Cons 't' 1)))
+(Cons 'c' (Cons 'a' 2))
+(Cons 'c' 3)
+4
+ + +

But where are all the informations? (+1) and 0?

+
+
+

κατα-morphism: Missing Information

+

Where is the missing information?

+ +

First example, make length on [Char]

+
+
+

κατα-morphism: Type work

+

+data StrF a = Cons Char a | Nil
+data Str' = StrF Str'
+
+-- generalize the construction of Str to other datatype
+-- Mu: type fixed point
+-- Mu :: (* -> *) -> *
+
+data Mu f = InF { outF :: f (Mu f) }
+data Str = Mu StrF
+
+-- Example
+foo=InF { outF = Cons 'f'
+        (InF { outF = Cons 'o'
+            (InF { outF = Cons 'o'
+                (InF { outF = Nil })})})}
+ + +
+
+

κατα-morphism: missing information retrieved

+
type Algebra f a = f a -> a
+instance Functor (StrF a) =
+    fmap f (Cons c x) = Cons c (f x)
+    fmap _ Nil = Nil
+ +
cata :: Functor f => Algebra f a -> Mu f -> a
+cata f = f . fmap (cata f) . outF
+ + + +
+
+

κατα-morphism: Finally length

+

All needed information for making length.

+
instance Functor (StrF a) =
+    fmap f (Cons c x) = Cons c (f x)
+    fmap _ Nil = Nil
+
+length' :: Str -> Int
+length' = cata phi where
+    phi :: Algebra StrF Int -- StrF Int -> Int
+    phi (Cons a b) = 1 + b
+    phi Nil = 0
+
+main = do
+    l <- length' $ stringToStr "Toto"
+    ...
+
+
+

κατα-morphism: extension to Trees

+

Once you get the trick, it is easy to extent to most Functor.

+
type Tree = Mu TreeF
+data TreeF x = Node Int [x]
+
+instance Functor TreeF where
+  fmap f (Node e xs) = Node e (fmap f xs)
+
+depth = cata phi where
+  phi :: Algebra TreeF Int -- TreeF Int -> Int
+  phi (Node x sons) = 1 + foldr max 0 sons
+
+
+

Conclusion

+

Category Theory oriented Programming:

+ +

No cat were harmed in the making of this presentation.

+
diff --git a/content/html/fr/blog/Category-Theory-Presentation.erb b/content/html/fr/blog/Category-Theory-Presentation.erb new file mode 100644 index 000000000..7fde2f554 --- /dev/null +++ b/content/html/fr/blog/Category-Theory-Presentation.erb @@ -0,0 +1,1000 @@ +----- +isHidden: false +menupriority: 1 +kind: article +created_at: 2012-12-12T10:06:40+02:00 +title: Category Theory Presentation +author_name: Yann Esposito +author_uri: yannesposito.com +tags: + - category theory + - math + - functor +----- +Cateogry of Hask's endofunctors + +

Yesterday I was happy to make a presentation about Category Theory at Riviera Scala Clojure Meetup (note I used only Haskell for my examples).

+ + + +

If you don't want to read them through an HTML presentations framework or downloading a big PDF +just continue to read as a standard web page. +

+ +
+\(\newcommand{\F}{\mathbf{F}}\) +\(\newcommand{\E}{\mathbf{E}}\) +\(\newcommand{\C}{\mathcal{C}}\) +\(\newcommand{\D}{\mathcal{D}}\) +\(\newcommand{\id}{\mathrm{id}}\) +\(\newcommand{\ob}[1]{\mathrm{ob}(#1)}\) +\(\newcommand{\hom}[1]{\mathrm{hom}(#1)}\) +\(\newcommand{\Set}{\mathbf{Set}}\) +\(\newcommand{\Mon}{\mathbf{Mon}}\) +\(\newcommand{\Vec}{\mathbf{Vec}}\) +\(\newcommand{\Grp}{\mathbf{Grp}}\) +\(\newcommand{\Rng}{\mathbf{Rng}}\) +\(\newcommand{\ML}{\mathbf{ML}}\) +\(\newcommand{\Hask}{\mathbf{Hask}}\) +\(\newcommand{\Cat}{\mathbf{Cat}}\) +\(\newcommand{\fmap}{\mathtt{fmap}}\) +
+ +
+

Category Theory & Programming

+
for Rivieria Scala Clojure (Note this presentation uses Haskell)
+by Yann Esposito +
+ + @yogsototh, + + + +yogsototh + +
+
+
ENTER FULLSCREEN
+ HTML presentation: use arrows, space, swipe to navigate. +
+
+
+

Plan

+ +
+
+

Not really about: Cat & glory

+
+Cat n glory
credit to Tokuhiro Kawai (川井徳寛)
+
+ + + +
+
+

General Overview

+
+Samuel Eilenberg Saunders Mac Lane +
+ +

Recent Math Field
1942-45, Samuel Eilenberg & Saunders Mac Lane

+

Certainly one of the more abstract branches of math

+ +

+★: When is one thing equal to some other thing?, Barry Mazur, 2007
☆: Physics, Topology, Logic and Computation: A Rosetta Stone, John C. Baez, Mike Stay, 2009 +

+ + +
+
+

From a Programmer perspective

+
+

Category Theory is a new language/framework for Math

+
+ +
+
+

Math Programming relation

+Buddha Fractal +

Programming is doing Math

+

Strong relations between type theory and category theory.

+

Not convinced?
Certainly a vocabulary problem.

+

One of the goal of Category Theory is to create a homogeneous vocabulary between different disciplines.

+
+
+

Vocabulary

+mind blown +

Math vocabulary used in this presentation:

+
+

Category, Morphism, Associativity, Preorder, Functor, Endofunctor, Categorial property, Commutative diagram, Isomorph, Initial, Dual, Monoid, Natural transformation, Monad, Klesli arrows, κατα-morphism, ...

+
+
+
+

Programmer Translation

+lolcat + + + + + + + + +
+Mathematician + +Programmer +
+Morphism + +Arrow +
+Monoid + +String-like +
+Preorder + +Acyclic graph +
+Isomorph + +The same +
+Natural transformation + +rearrangement function +
+Funny Category + +LOLCat +
+ + +
+
+

Plan

+ +
+
+

Category

+ +

A way of representing things and ways to go between things.

+ +

A Category \(\mathcal{C}\) is defined by:

+ +
+
+

Category: Objects

+ +objects + +

\(\ob{\mathcal{C}}\) is a collection

+
+
+

Category: Morphisms

+ +morphisms + +

\(A\) and \(B\) objects of \(\C\)
+\(\hom{A,B}\) is a collection of morphisms
+\(f:A→B\) denote the fact \(f\) belongs to \(\hom{A,B}\)

+

\(\hom{\C}\) the collection of all morphisms of \(\C\)

+
+
+

Category: Composition

+

Composition (∘): associate to each couple \(f:A→B, g:B→C\) + $$g∘f:A\rightarrow C$$ +

+composition +
+
+

Category laws: neutral element

+

for each object \(X\), there is an \(\id_X:X→X\),
+such that for each \(f:A→B\):

+identity +
+
+

Category laws: Associativity

+

Composition is associative:

+associative composition +
+
+

Commutative diagrams

+ +

Two path with the same source and destination are equal.

+
+ Commutative Diagram (Associativity) +
+ \((h∘g)∘f = h∘(g∘f) \) +
+
+
+ Commutative Diagram (Identity law) +
+ \(id_B∘f = f = f∘id_A \) +
+
+
+
+

Question Time!

+ +
+ +
+- French-only joke - +
+
+
+
+

Can this be a category?

+

\(\ob{\C},\hom{\C}\) fixed, is there a valid ∘?

+
+ Category example 1 +
+ YES +
+
+
+ Category example 2 +
+ no candidate for \(g∘f\) +
NO +
+
+
+ Category example 3 +
+ YES +
+
+
+
+

Can this be a category?

+
+ Category example 4 +
+ no candidate for \(f:C→B\) +
NO +
+
+
+ Category example 5 +
+ \((h∘g)∘f=\id_B∘f=f\)
+ \(h∘(g∘f)=h∘\id_A=h\)
+ but \(h≠f\)
+ NO +
+
+
+
+

Categories Examples

+ +
+Basket of cats +
+- Basket of Cats - +
+
+
+
+

Category \(\Set\)

+ + + + +
+
+

Categories Everywhere?

+Cats everywhere + +
+
+

Smaller Examples

+ +

Strings

+Monoids are one object categories + + +
+
+

Finite Example?

+ +

Graph

+
+Each graph is a category +
+ + +
+
+

Number construction

+ +

Each Numbers as a whole category

+Each number as a category +
+
+

Degenerated Categories: Monoids

+ +Monoids are one object categories +

Each Monoid \((M,e,⊙): \ob{M}=\{∙\},\hom{M}=M,\circ = ⊙\)

+

Only one object.

+

Examples:

+ +
+
+

Degenerated Categories: Preorders \((P,≤)\)

+ + + +

At most one morphism between two objects.

+ +preorder category +
+
+

Degenerated Categories: Discrete Categories

+ +Any set can be a category +

Any Set

+

Any set \(E: \ob{E}=E, \hom{x,y}=\{x\} ⇔ x=y \)

+

Only identities

+
+
+

Choice

+

The same object can be seen in many different way as a category.

+

You can choose what are object, morphisms and composition.

+

ex: Str and discrete(Σ*)

+
+
+

Categorical Properties

+ +

Any property which can be expressed in term of category, objects, morphism and composition.

+ + +
+
+

Isomorph

+

isomorph cats isomorphism: \(f:A→B\) which can be "undone" i.e.
\(∃g:B→A\), \(g∘f=id_A\) & \(f∘g=id_B\)
in this case, \(A\) & \(B\) are isomorphic.

+

A≌B means A and B are essentially the same.
In Category Theory, = is in fact mostly .
For example in commutative diagrams.

+
+
+

Functor

+ +

A functor is a mapping between two categories. +Let \(\C\) and \(\D\) be two categories. +A functor \(\F\) from \(\C\) to \(\D\):

+ +
+
+

Functor Example (ob → ob)

+ +Functor +
+
+

Functor Example (hom → hom)

+ +Functor +
+
+

Functor Example

+ +Functor +
+
+

Endofunctors

+ +

An endofunctor for \(\C\) is a functor \(F:\C→\C\).

+Endofunctor +
+
+

Category of Categories

+ + + +

Categories and functors form a category: \(\Cat\)

+ +
+
+

Plan

+ +
+
+

Hask

+ +

Category \(\Hask\):

+ +Haskell Category Representation + + + +

Forget glitches because of undefined.

+
+
+

Haskell Kinds

+

In Haskell some types can take type variable(s). Typically: [a].

+

Types have kinds; The kind is to type what type is to function. Kind are the types for types (so meta).

+
Int, Char :: *
+[], Maybe :: * -> *
+(,), (->) :: * -> * -> *
+[Int], Maybe Char, Maybe [Int] :: *
+
+
+

Haskell Types

+

Sometimes, the type determine a lot about the function:

+
fst :: (a,b) -> a -- Only one choice
+snd :: (a,b) -> b -- Only one choice
+f :: a -> [a]     -- Many choices
+-- Possibilities: f x=[], or [x], or [x,x] or [x,...,x]
+
+? :: [a] -> [a] -- Many choices
+-- can only rearrange: duplicate/remove/reorder elements
+-- for example: the type of addOne isn't [a] -> [a]
+addOne l = map (+1) l
+-- The (+1) force 'a' to be a Num.
+ +

+

★:Theorems for free!, Philip Wadler, 1989

+
+
+

Haskell Functor vs \(\Hask\) Functor

+ +

A Haskell Functor is a type F :: * -> * which belong to the type class Functor ; thus instantiate +fmap :: (a -> b) -> (F a -> F b). + +

& F: \(\ob{\Hask}→\ob{\Hask}\)
& fmap: \(\hom{\Hask}→\hom{\Hask}\) + +

The couple (F,fmap) is a \(\Hask\)'s functor if for any x :: F a:

+ +
+
+

Haskell Functors Example: Maybe

+ +
data Maybe a = Just a | Nothing
+instance Functor Maybe where
+    fmap :: (a -> b) -> (Maybe a -> Maybe b)
+    fmap f (Just a) = Just (f a)
+    fmap f Nothing = Nothing
+
fmap (+1) (Just 1) == Just 2
+fmap (+1) Nothing  == Nothing
+fmap head (Just [1,2,3]) == Just 1
+
+
+

Haskell Functors Example: List

+ +
instance Functor ([]) where
+	fmap :: (a -> b) -> [a] -> [b]
+	fmap = map
+
fmap (+1) [1,2,3]           == [2,3,4]
+fmap (+1) []                == []
+fmap head [[1,2,3],[4,5,6]] == [1,4]
+
+
+

Haskell Functors for the programmer

+

Functor is a type class used for types that can be mapped over.

+ +
+
+

Haskell Functor intuition

+ +

Put normal function inside a container. Ex: list, trees...

+ +Haskell Functor as a box play +

+
+

Haskell Functor properties

+ +

Haskell Functors are:

+ + +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

"Non Haskell" Hask's Functors

+

A simple basic example is the \(id_\Hask\) functor. It simply cannot be expressed as a couple (F,fmap) where

+ +

Another example:

+ +
+
+

Also Functor inside \(\Hask\)

+

\(\mathtt{[a]}∈\ob{\Hask}\) but is also a category. Idem for Int.

+

length is a Functor from the category [a] to the cateogry Int:

+ +

+ +
+ +
+
+

Category of \(\Hask\) Endofunctors

+Category of Hask endofunctors +
+
+

Category of Functors

+

If \(\C\) is small (\(\hom{\C}\) is a set). All functors from \(\C\) to some category \(\D\) form the category \(\mathrm{Func}(\C,\D)\).

+ +

\(\mathrm{Func}(\C,\C)\) is the category of endofunctors of \(\C\).

+
+
+

Natural Transformations

+

Let \(F\) and \(G\) be two functors from \(\C\) to \(\D\).

+

Natural transformation commutative diagram A natural transformation: familly η ; \(η_X\in\hom{\D}\) for \(X\in\ob{\C}\) s.t.

+

ex: between Haskell functors; F a -> G a
Rearragement functions only.

+
+
+

Natural Transformation Examples (1/4)

+
data Tree a = Empty | Node a [Tree a]
+toTree :: [a] -> Tree a
+toTree [] = Empty
+toTree (x:xs) = Node x [toTree xs]
+ +

toTree is a natural transformation. It is also a morphism from [] to Tree in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram +
+ + +
+
+

Natural Transformation Examples (2/4)

+
data Tree a = Empty | Node a [Tree a]
+toList :: Tree a -> [a]
+toList Empty = []
+toList (Node x l) = [x] ++ concat (map toList l)
+ +

toList is a natural transformation. It is also a morphism from Tree to [] in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram
toList . toTree = id & toTree . toList = id &
therefore [] & Tree are isomorph.
+
+ + +
+
+

Natural Transformation Examples (3/4)

+
toMaybe :: [a] -> Maybe a
+toMaybe [] = Nothing
+toMaybe (x:xs) = Just x
+ +

toMaybe is a natural transformation. It is also a morphism from [] to Maybe in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram +
+ + +
+
+

Natural Transformation Examples (4/4)

+
mToList :: Maybe a -> [a]
+mToList Nothing = []
+mToList Just x  = [x]
+ +

toMaybe is a natural transformation. It is also a morphism from [] to Maybe in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+relation between [] and Maybe
There is no isomorphism.
Hint: Bool lists longer than 1.
+
+ + +
+
+

Composition problem

+

The Problem; example with lists:

+
f x = [x]       ⇒ f 1 = [1]   ⇒ (f.f) 1 = [[1]] ✗
+g x = [x+1]     ⇒ g 1 = [2]   ⇒ (g.g) 1 = ERROR [2]+1 ✗
+h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h.h) 1 = ERROR [2,3]+1 ✗ 
+ +

The same problem with most f :: a -> F a functions and functor F.

+
+
+

Composition Fixable?

+

How to fix that? We want to construct an operator which is able to compose:

+

f :: a -> F b & g :: b -> F c.

+

More specifically we want to create an operator ◎ of type

+

◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)

+

Note: if F = I, ◎ = (.).

+
+
+

Fix Composition (1/2)

+

Goal, find: ◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)
f :: a -> F b, g :: b -> F c:

+ +
+
+

Fix Composition (2/2)

+

Goal, find: ◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)
f :: a -> F b, g :: b -> F c, f x :: F b:

+ +
+
+

Necessary laws

+

For ◎ to work like composition, we need join to hold the following properties:

+ +
+
+

Klesli composition

+

Now the composition works as expected. In Haskell ◎ is <=< in Control.Monad.

+

g <=< f = \x -> join ((fmap g) (f x))

+
f x = [x]       ⇒ f 1 = [1]   ⇒ (f <=< f) 1 = [1] ✓
+g x = [x+1]     ⇒ g 1 = [2]   ⇒ (g <=< g) 1 = [3] ✓
+h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h <=< h) 1 = [3,6,4,9] ✓
+ + +
+
+

We reinvented Monads!

+

A monad is a triplet (M,⊙,η) where

+ +

Satisfying

+ +
+
+

Compare with Monoid

+

A Monoid is a triplet \((E,∙,e)\) s.t.

+ +

Satisfying

+ +
+
+

Monads are just Monoids

+
+

A Monad is just a monoid in the category of endofunctors, what's the problem?

+
+

The real sentence was:

+
+

All told, a monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor.

+
+
+
+

Example: List

+ +
-- In Haskell ⊙ is "join" in "Control.Monad"
+join :: [[a]] -> [a]
+join = concat
+
+-- In Haskell the "return" function (unfortunate name)
+η :: a -> [a]
+η x = [x]
+ + +
+
+

Example: List (law verification)

+

Example: List is a functor (join is ⊙)

+ +
join [ join [[x,y,...,z]] ] = join [[x,y,...,z]]
+                            = join (join [[[x,y,...,z]]])
+join (η [x]) = [x] = join [η x]
+ +

Therefore ([],join,η) is a monad.

+
+
+

Monads useful?

+

A LOT of monad tutorial on the net. Just one example; the State Monad

+

DrawScene to State Screen DrawScene ; still pure.

+
main = drawImage (width,height)
+
+drawImage :: Screen -> DrawScene
+drawImage screen = do
+    drawPoint p screen
+    drawCircle c screen
+    drawRectangle r screen
+
+drawPoint point screen = ...
+drawCircle circle screen = ...
+drawRectangle rectangle screen = ...
+
main = do
+    put (Screen 1024 768)
+    drawImage
+
+drawImage :: State Screen DrawScene
+drawImage = do
+    drawPoint p
+    drawCircle c
+    drawRectangle r
+
+drawPoint :: Point -> State Screen DrawScene
+drawPoint p = do
+    Screen width height <- get
+    ...
+
+
+

fold

+fold +
+
+

κατα-morphism

+catamorphism +
+
+

κατα-morphism: fold generalization

+

acc type of the "accumulator":
fold :: (acc -> a -> acc) -> acc -> [a] -> acc

+

Idea: put the accumulated value inside the type.

+
-- Equivalent to fold (+1) 0 "cata"
+(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' Nil))))
+(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' 0))))
+(Cons 'c' (Cons 'a' (Cons 't' 1)))
+(Cons 'c' (Cons 'a' 2))
+(Cons 'c' 3)
+4
+ + +

But where are all the informations? (+1) and 0?

+
+
+

κατα-morphism: Missing Information

+

Where is the missing information?

+ +

First example, make length on [Char]

+
+
+

κατα-morphism: Type work

+

+data StrF a = Cons Char a | Nil
+data Str' = StrF Str'
+
+-- generalize the construction of Str to other datatype
+-- Mu: type fixed point
+-- Mu :: (* -> *) -> *
+
+data Mu f = InF { outF :: f (Mu f) }
+data Str = Mu StrF
+
+-- Example
+foo=InF { outF = Cons 'f'
+        (InF { outF = Cons 'o'
+            (InF { outF = Cons 'o'
+                (InF { outF = Nil })})})}
+ + +
+
+

κατα-morphism: missing information retrieved

+
type Algebra f a = f a -> a
+instance Functor (StrF a) =
+    fmap f (Cons c x) = Cons c (f x)
+    fmap _ Nil = Nil
+ +
cata :: Functor f => Algebra f a -> Mu f -> a
+cata f = f . fmap (cata f) . outF
+ + + +
+
+

κατα-morphism: Finally length

+

All needed information for making length.

+
instance Functor (StrF a) =
+    fmap f (Cons c x) = Cons c (f x)
+    fmap _ Nil = Nil
+
+length' :: Str -> Int
+length' = cata phi where
+    phi :: Algebra StrF Int -- StrF Int -> Int
+    phi (Cons a b) = 1 + b
+    phi Nil = 0
+
+main = do
+    l <- length' $ stringToStr "Toto"
+    ...
+
+
+

κατα-morphism: extension to Trees

+

Once you get the trick, it is easy to extent to most Functor.

+
type Tree = Mu TreeF
+data TreeF x = Node Int [x]
+
+instance Functor TreeF where
+  fmap f (Node e xs) = Node e (fmap f xs)
+
+depth = cata phi where
+  phi :: Algebra TreeF Int -- TreeF Int -> Int
+  phi (Node x sons) = 1 + foldr max 0 sons
+
+
+

Conclusion

+

Category Theory oriented Programming:

+ +

No cat were harmed in the making of this presentation.

+
diff --git a/crash.log b/crash.log index c3e62aabd..94e6223b9 100644 --- a/crash.log +++ b/crash.log @@ -1,155 +1,44 @@ -Crashlog created at 2012-10-05 10:57:23 +0200 +Crashlog created at Wed Dec 12 10:36:06 +0100 2012 === MESSAGE: -Sass::SyntaxError: Invalid CSS after "italic": expected expression (e.g. 1px, bold), was ";" +NoMethodError: undefined method `find_all' for Gem::Specification:Class === COMPILATION STACK: - - [item] /css/main/ (rep default) + (empty) === BACKTRACE: - 0. content/css/main.sass:631 - 1. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/scss/parser.rb:1010:in `expected' - 2. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/script/lexer.rb:191:in `expected!' - 3. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/script/parser.rb:465:in `assert_done' - 4. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/script/parser.rb:50:in `parse' - 5. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/script/parser.rb:140:in `parse' - 6. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/script.rb:31:in `parse' - 7. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:832:in `parse_script' - 8. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:593:in `parse_property' - 9. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:582:in `parse_property_or_rule' - 10. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:563:in `parse_line' - 11. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:456:in `build_tree' - 12. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:475:in `block in append_children' - 13. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:474:in `each' - 14. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:474:in `append_children' - 15. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:465:in `block in build_tree' - 16. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:458:in `each' - 17. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:458:in `build_tree' - 18. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:475:in `block in append_children' - 19. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:474:in `each' - 20. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:474:in `append_children' - 21. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:330:in `_to_tree' - 22. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:300:in `_render' - 23. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib/sass/engine.rb:247:in `render' - 24. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/filters/sass.rb:62:in `run' - 25. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/result_data/item_rep.rb:343:in `filter' - 26. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/item_rep_proxy.rb:47:in `filter' - 27. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/rule_context.rb:54:in `filter' - 28. ./Rules:12:in `block in load' - 29. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/rule.rb:68:in `instance_eval' - 30. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/rule.rb:68:in `apply_to' - 31. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/compiler.rb:381:in `compile_rep' - 32. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/compiler.rb:337:in `block in compile_reps' - 33. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/compiler.rb:330:in `loop' - 34. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/compiler.rb:330:in `compile_reps' - 35. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/compilation/compiler.rb:85:in `run' - 36. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/base/source_data/site.rb:57:in `compile' - 37. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/commands/compile.rb:57:in `run' - 38. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/command_runner.rb:14:in `block in call' - 39. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/error_handler.rb:63:in `handle_while' - 40. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/error_handler.rb:26:in `handle_while' - 41. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/command_runner.rb:13:in `call' - 42. /var/lib/gems/1.9.1/gems/cri-2.3.0/lib/cri/command_dsl.rb:185:in `block in runner' - 43. /var/lib/gems/1.9.1/gems/cri-2.3.0/lib/cri/command.rb:296:in `call' - 44. /var/lib/gems/1.9.1/gems/cri-2.3.0/lib/cri/command.rb:296:in `run_this' - 45. /var/lib/gems/1.9.1/gems/cri-2.3.0/lib/cri/command.rb:249:in `run' - 46. /var/lib/gems/1.9.1/gems/cri-2.3.0/lib/cri/command.rb:262:in `run' - 47. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli.rb:47:in `block in run' - 48. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/error_handler.rb:63:in `handle_while' - 49. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli/error_handler.rb:26:in `handle_while' - 50. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib/nanoc/cli.rb:44:in `run' - 51. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/bin/nanoc:19:in `' - 52. /usr/local/bin/nanoc:19:in `load' - 53. /usr/local/bin/nanoc:19:in `
' + 0. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:272:in `gems_and_versions' + 1. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:217:in `write_verbose_error' + 2. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:92:in `print_error' + 3. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:92:in `open' + 4. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:92:in `print_error' + 5. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:70:in `handle_while' + 6. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:26:in `handle_while' + 7. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/command_runner.rb:13:in `call' + 8. /Library/Ruby/Gems/1.8/gems/cri-2.3.0/lib/cri/command_dsl.rb:185:in `runner' + 9. /Library/Ruby/Gems/1.8/gems/cri-2.3.0/lib/cri/command.rb:296:in `call' + 10. /Library/Ruby/Gems/1.8/gems/cri-2.3.0/lib/cri/command.rb:296:in `run_this' + 11. /Library/Ruby/Gems/1.8/gems/cri-2.3.0/lib/cri/command.rb:249:in `run' + 12. /Library/Ruby/Gems/1.8/gems/cri-2.3.0/lib/cri/command.rb:262:in `run' + 13. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli.rb:53:in `run' + 14. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:63:in `handle_while' + 15. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli/error_handler.rb:26:in `handle_while' + 16. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/lib/nanoc/cli.rb:50:in `run' + 17. /Library/Ruby/Gems/1.8/gems/nanoc-3.4.1/bin/nanoc:19 + 18. /usr/bin/nanoc:19:in `load' + 19. /usr/bin/nanoc:19 === VERSION INFORMATION: -nanoc 3.4.0 © 2007-2012 Denis Defreyne. -Running ruby 1.9.3 (2011-10-30) on i686-linux with RubyGems 1.8.11. +nanoc 3.4.1 © 2007-2012 Denis Defreyne. +Running ruby 1.8.7 (2012-02-08) on universal-darwin12.0 with RubyGems 1.3.6. + +=== SYSTEM INFORMATION: + +Darwin YMac.local 12.2.0 Darwin Kernel Version 12.2.0: Sat Aug 25 00:48:52 PDT 2012; root:xnu-2050.18.24~1/RELEASE_X86_64 x86_64 === INSTALLED GEMS: - builder 3.0.0 - colored 1.2 - cri 2.2.1, 2.3.0 - kgio 2.7.4 - kramdown 0.13.5, 0.13.7 - mime-types 1.18 - nanoc 3.3.6, 3.4.0 - rack 1.4.1 - rack-contrib 1.1.0 - rack-rewrite 1.2.1 - raindrops 0.8.0, 0.9.0 - rainpress 1.0 - rake 0.9.2.2 - sass 3.1.16, 3.1.19 - spox-plist 3.0.1 - spox-textpow 0.10.3 - spox-ultraviolet 0.10.5 - unicorn 4.3.1 - -=== ENVIRONMENT: - -CAPP_BUILD => "/home/y/tmp/cappuccino/Build" -COLORTERM => "gnome-terminal" -DBUS_SESSION_BUS_ADDRESS => "unix:abstract=/tmp/dbus-Hp98B7Xjn9,guid=15354c350aefacc311107e5100000061" -DEFAULTS_PATH => "/usr/share/gconf/Lubuntu.default.path" -DEFAULT_GHC_OPTIONS => "-O2" -DESKTOP_SESSION => "Lubuntu" -DISPLAY => ":0" -GDMSESSION => "Lubuntu" -GDM_LANG => "fr" -GNOME_KEYRING_CONTROL => "/tmp/keyring-S5aOL0" -GNOME_KEYRING_PID => "1575" -GTK_MODULES => "canberra-gtk-module:canberra-gtk-module" -HOME => "/home/y" -LANG => "fr_FR.UTF-8" -LANGUAGE => "fr:en" -LOGNAME => "y" -LS_COLORS => "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:" -MANDATORY_PATH => "/usr/share/gconf/Lubuntu.mandatory.path" -OLDPWD => "/home/y/Sites/webroot" -PATH => "/home/y/narwhal/bin:/home/y/.cabal/bin:/home/y/bin:/usr/local/bin:/usr/bin:/bin:/usr/games" -PWD => "/home/y/Sites/webroot" -SAL_USE_VCLPLUGIN => "gtk" -SHELL => "/usr/bin/zsh" -SHLVL => "3" -SSH_AGENT_PID => "1659" -SSH_AUTH_SOCK => "/tmp/keyring-S5aOL0/ssh" -TERM => "xterm" -UBUNTU_MENUPROXY => "libappmenu.so" -USER => "y" -USERNAME => "y" -WINDOWID => "39845892" -WINDOWPATH => "7" -XAUTHORITY => "/var/run/gdm/auth-for-y-FEu9Ou/database" -XDG_CONFIG_DIRS => "/etc/xdg/lubuntu/:/etc/xdg/xdg-Lubuntu:/etc/xdg" -XDG_CONFIG_HOME => "/home/y/.config" -XDG_CURRENT_DESKTOP => "LXDE" -XDG_DATA_DIRS => "/etc/xdg/lubuntu:/usr/share/Lubuntu:/usr/local/share/:/usr/share/:/usr/share:/usr/share/gdm:/var/lib/menu-xdg" -XDG_MENU_PREFIX => "lxde-" -XDG_SESSION_COOKIE => "2967f5ac8d4676a86149144a000004ac-1349250736.25162-1033128370" -_ => "/usr/local/bin/nanoc" -_LXSESSION_PID => "1592" -__GIT_PROMPT_DIR => "/home/y/.zsh/git-prompt" - -=== $LOAD_PATH: - - 0. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib - 1. /var/lib/gems/1.9.1/gems/nanoc-3.4.0/lib - 2. /var/lib/gems/1.9.1/gems/colored-1.2/lib - 3. /var/lib/gems/1.9.1/gems/cri-2.3.0/lib - 4. /var/lib/gems/1.9.1/gems/builder-3.0.0/lib - 5. /var/lib/gems/1.9.1/gems/kramdown-0.13.7/lib - 6. /var/lib/gems/1.9.1/gems/sass-3.1.19/lib - 7. /usr/local/lib/site_ruby/1.9.1 - 8. /usr/local/lib/site_ruby/1.9.1/i686-linux - 9. /usr/local/lib/site_ruby - 10. /usr/lib/ruby/vendor_ruby/1.9.1 - 11. /usr/lib/ruby/vendor_ruby/1.9.1/i686-linux - 12. /usr/lib/ruby/vendor_ruby - 13. /usr/lib/ruby/1.9.1 - 14. /usr/lib/ruby/1.9.1/i686-linux diff --git a/img_latest_blog_dir b/img_latest_blog_dir index 1c72e24d9..fa9bee8c2 120000 --- a/img_latest_blog_dir +++ b/img_latest_blog_dir @@ -1 +1 @@ -output/Scratch/img/blog/Haskell-OpenGL-Mandelbrot \ No newline at end of file +./output/Scratch/img/blog/Category-Theory-Presentation \ No newline at end of file diff --git a/latest.ymd b/latest.ymd index 1b8b8e4aa..5a7fd9383 120000 --- a/latest.ymd +++ b/latest.ymd @@ -1 +1 @@ -multi/blog/Haskell-OpenGL-Mandelbrot.md \ No newline at end of file +multi/blog/Category-Theory-Presentation.md \ No newline at end of file diff --git a/multi/blog/Category-Theory-Presentation.erb b/multi/blog/Category-Theory-Presentation.erb new file mode 100644 index 000000000..d0b5cb676 --- /dev/null +++ b/multi/blog/Category-Theory-Presentation.erb @@ -0,0 +1,1001 @@ +----- +isHidden: false +menupriority: 1 +kind: article +created_at: 2012-12-12T10:06:40+02:00 +en: title: Category Theory Presentation +fr: title: Category Theory Presentation +author_name: Yann Esposito +author_uri: yannesposito.com +tags: + - category theory + - math + - functor +----- +Cateogry of Hask's endofunctors + +

Yesterday I was happy to make a presentation about Category Theory at Riviera Scala Clojure Meetup (note I used only Haskell for my examples).

+ + + +

If you don't want to read them through an HTML presentations framework or downloading a big PDF +just continue to read as a standard web page. +

+ +
+\(\newcommand{\F}{\mathbf{F}}\) +\(\newcommand{\E}{\mathbf{E}}\) +\(\newcommand{\C}{\mathcal{C}}\) +\(\newcommand{\D}{\mathcal{D}}\) +\(\newcommand{\id}{\mathrm{id}}\) +\(\newcommand{\ob}[1]{\mathrm{ob}(#1)}\) +\(\newcommand{\hom}[1]{\mathrm{hom}(#1)}\) +\(\newcommand{\Set}{\mathbf{Set}}\) +\(\newcommand{\Mon}{\mathbf{Mon}}\) +\(\newcommand{\Vec}{\mathbf{Vec}}\) +\(\newcommand{\Grp}{\mathbf{Grp}}\) +\(\newcommand{\Rng}{\mathbf{Rng}}\) +\(\newcommand{\ML}{\mathbf{ML}}\) +\(\newcommand{\Hask}{\mathbf{Hask}}\) +\(\newcommand{\Cat}{\mathbf{Cat}}\) +\(\newcommand{\fmap}{\mathtt{fmap}}\) +
+ +
+

Category Theory & Programming

+
for Rivieria Scala Clojure (Note this presentation uses Haskell)
+by Yann Esposito +
+ + @yogsototh, + + + +yogsototh + +
+
+
ENTER FULLSCREEN
+ HTML presentation: use arrows, space, swipe to navigate. +
+
+
+

Plan

+
    +
  • General overview
  • +
  • Definitions
  • +
  • Applications
  • +
+
+
+

Not really about: Cat & glory

+
+Cat n glory
credit to Tokuhiro Kawai (川井徳寛)
+
+ + + +
+
+

General Overview

+
+Samuel Eilenberg Saunders Mac Lane +
+ +

Recent Math Field
1942-45, Samuel Eilenberg & Saunders Mac Lane

+

Certainly one of the more abstract branches of math

+
    +
  • New math foundation
    formalism abstraction, package entire theory
  • +
  • Bridge between disciplines
    Physics, Quantum Physics, Topology, Logic, Computer Science
  • +
+

+★: When is one thing equal to some other thing?, Barry Mazur, 2007
☆: Physics, Topology, Logic and Computation: A Rosetta Stone, John C. Baez, Mike Stay, 2009 +

+ + +
+
+

From a Programmer perspective

+
+

Category Theory is a new language/framework for Math

+
+
    +
  • Another way of thinking
  • +
  • Extremely efficient for generalization
  • +
+
+
+

Math Programming relation

+Buddha Fractal +

Programming is doing Math

+

Strong relations between type theory and category theory.

+

Not convinced?
Certainly a vocabulary problem.

+

One of the goal of Category Theory is to create a homogeneous vocabulary between different disciplines.

+
+
+

Vocabulary

+mind blown +

Math vocabulary used in this presentation:

+
+

Category, Morphism, Associativity, Preorder, Functor, Endofunctor, Categorial property, Commutative diagram, Isomorph, Initial, Dual, Monoid, Natural transformation, Monad, Klesli arrows, κατα-morphism, ...

+
+
+
+

Programmer Translation

+lolcat + + + + + + + + +
+Mathematician + +Programmer +
+Morphism + +Arrow +
+Monoid + +String-like +
+Preorder + +Acyclic graph +
+Isomorph + +The same +
+Natural transformation + +rearrangement function +
+Funny Category + +LOLCat +
+ + +
+
+

Plan

+
    +
  • General overview
  • +
  • Definitions +
      +
    • Category
    • +
    • Intuition
    • +
    • Examples
    • +
    • Functor
    • +
    • Examples
    • +
    +
  • +
  • Applications
  • +
+
+
+

Category

+ +

A way of representing things and ways to go between things.

+ +

A Category \(\mathcal{C}\) is defined by:

+
    +
  • Objects \(\ob{C}\),
  • +
  • Morphisms \(\hom{C}\),
  • +
  • a Composition law (∘)
  • +
  • obeying some Properties.
  • +
+
+
+

Category: Objects

+ +objects + +

\(\ob{\mathcal{C}}\) is a collection

+
+
+

Category: Morphisms

+ +morphisms + +

\(A\) and \(B\) objects of \(\C\)
+\(\hom{A,B}\) is a collection of morphisms
+\(f:A→B\) denote the fact \(f\) belongs to \(\hom{A,B}\)

+

\(\hom{\C}\) the collection of all morphisms of \(\C\)

+
+
+

Category: Composition

+

Composition (∘): associate to each couple \(f:A→B, g:B→C\) + $$g∘f:A\rightarrow C$$ +

+composition +
+
+

Category laws: neutral element

+

for each object \(X\), there is an \(\id_X:X→X\),
+such that for each \(f:A→B\):

+identity +
+
+

Category laws: Associativity

+

Composition is associative:

+associative composition +
+
+

Commutative diagrams

+ +

Two path with the same source and destination are equal.

+
+ Commutative Diagram (Associativity) +
+ \((h∘g)∘f = h∘(g∘f) \) +
+
+
+ Commutative Diagram (Identity law) +
+ \(id_B∘f = f = f∘id_A \) +
+
+
+
+

Question Time!

+ +
+ +
+- French-only joke - +
+
+
+
+

Can this be a category?

+

\(\ob{\C},\hom{\C}\) fixed, is there a valid ∘?

+
+ Category example 1 +
+ YES +
+
+
+ Category example 2 +
+ no candidate for \(g∘f\) +
NO +
+
+
+ Category example 3 +
+ YES +
+
+
+
+

Can this be a category?

+
+ Category example 4 +
+ no candidate for \(f:C→B\) +
NO +
+
+
+ Category example 5 +
+ \((h∘g)∘f=\id_B∘f=f\)
+ \(h∘(g∘f)=h∘\id_A=h\)
+ but \(h≠f\)
+ NO +
+
+
+
+

Categories Examples

+ +
+Basket of cats +
+- Basket of Cats - +
+
+
+
+

Category \(\Set\)

+ +
    +
  • \(\ob{\Set}\) are all the sets
  • +
  • \(\hom{E,F}\) are all functions from \(E\) to \(F\)
  • +
  • ∘ is functions composition
  • +
+ +
    +
  • \(\ob{\Set}\) is a proper class ; not a set
  • +
  • \(\hom{E,F}\) is a set
  • +
  • \(\Set\) is then a locally small category
  • +
+
+
+

Categories Everywhere?

+Cats everywhere +
    +
  • \(\Mon\): (monoids, monoid morphisms,∘)
  • +
  • \(\Vec\): (Vectorial spaces, linear functions,∘)
  • +
  • \(\Grp\): (groups, group morphisms,∘)
  • +
  • \(\Rng\): (rings, ring morphisms,∘)
  • +
  • Any deductive system T: (theorems, proofs, proof concatenation)
  • +
  • \( \Hask\): (Haskell types, functions, (.) )
  • +
  • ...
  • +
+
+
+

Smaller Examples

+ +

Strings

+Monoids are one object categories +
    +
  • \(\ob{Str}\) is a singleton
  • +
  • \(\hom{Str}\) each string
  • +
  • ∘ is concatenation (++)
  • +
+
    +
  • "" ++ u = u = u ++ ""
  • +
  • (u ++ v) ++ w = u ++ (v ++ w)
  • +
+
+
+

Finite Example?

+ +

Graph

+
+Each graph is a category +
+
    +
  • \(\ob{G}\) are vertices
  • +
  • \(\hom{G}\) each path
  • +
  • ∘ is path concatenation
  • +
+
  • \(\ob{G}=\{X,Y,Z\}\), +
  • \(\hom{G}=\{ε,α,β,γ,αβ,βγ,...\}\) +
  • \(αβ∘γ=αβγ\) +
+
+
+

Number construction

+ +

Each Numbers as a whole category

+Each number as a category +
+
+

Degenerated Categories: Monoids

+ +Monoids are one object categories +

Each Monoid \((M,e,⊙): \ob{M}=\{∙\},\hom{M}=M,\circ = ⊙\)

+

Only one object.

+

Examples:

+
  • (Integer,0,+), (Integer,1,*), +
  • (Strings,"",++), for each a, ([a],[],++) +
+
+
+

Degenerated Categories: Preorders \((P,≤)\)

+ +
  • \(\ob{P}={P}\), +
  • \(\hom{x,y}=\{x≤y\} ⇔ x≤y\), +
  • \((y≤z) \circ (x≤y) = (x≤z) \) +
+ +

At most one morphism between two objects.

+ +preorder category +
+
+

Degenerated Categories: Discrete Categories

+ +Any set can be a category +

Any Set

+

Any set \(E: \ob{E}=E, \hom{x,y}=\{x\} ⇔ x=y \)

+

Only identities

+
+
+

Choice

+

The same object can be seen in many different way as a category.

+

You can choose what are object, morphisms and composition.

+

ex: Str and discrete(Σ*)

+
+
+

Categorical Properties

+ +

Any property which can be expressed in term of category, objects, morphism and composition.

+ +
  • Dual: \(\D\) is \(\C\) with reversed morphisms. +
  • Initial: \(Z\in\ob{\C}\) s.t. \(∀Y∈\ob{\C}, \#\hom{Z,Y}=1\) +
    Unique ("up to isormophism") +
  • Terminal: \(T\in\ob{\C}\) s.t. \(T\) is initial in the dual of \(\C\) +
  • Functor: structure preserving mapping between categories +
  • ... +
+
+
+

Isomorph

+

isomorph cats isomorphism: \(f:A→B\) which can be "undone" i.e.
\(∃g:B→A\), \(g∘f=id_A\) & \(f∘g=id_B\)
in this case, \(A\) & \(B\) are isomorphic.

+

A≌B means A and B are essentially the same.
In Category Theory, = is in fact mostly .
For example in commutative diagrams.

+
+
+

Functor

+ +

A functor is a mapping between two categories. +Let \(\C\) and \(\D\) be two categories. +A functor \(\F\) from \(\C\) to \(\D\):

+
    +
  • Associate objects: \(A\in\ob{\C}\) to \(\F(A)\in\ob{\D}\)
  • +
  • Associate morphisms: \(f:A\to B\) to \(\F(f) : \F(A) \to \F(B)\) + such that +
      +
    • \( \F (\)\(\id_X\)\()= \)\(\id\)\(\vphantom{\id}_{\F(}\)\(\vphantom{\id}_X\)\(\vphantom{\id}_{)} \),
    • +
    • \( \F (\)\(g∘f\)\()= \)\( \F(\)\(g\)\() \)\(\circ\)\( \F(\)\(f\)\() \)
    • +
    +
  • +
+
+
+

Functor Example (ob → ob)

+ +Functor +
+
+

Functor Example (hom → hom)

+ +Functor +
+
+

Functor Example

+ +Functor +
+
+

Endofunctors

+ +

An endofunctor for \(\C\) is a functor \(F:\C→\C\).

+Endofunctor +
+
+

Category of Categories

+ + + +

Categories and functors form a category: \(\Cat\)

+
  • \(\ob{\Cat}\) are categories +
  • \(\hom{\Cat}\) are functors +
  • ∘ is functor composition +
+
+
+

Plan

+
    +
  • General overview
  • +
  • Definitions
  • +
  • Applications +
      +
    • \(\Hask\) category +
    • Functors +
    • Natural transformations +
    • Monads +
    • κατα-morphisms +
    +
  • +
+
+
+

Hask

+ +

Category \(\Hask\):

+ +Haskell Category Representation + +
  • +\(\ob{\Hask} = \) Haskell types +
  • +\(\hom{\Hask} = \) Haskell functions +
  • +∘ = (.) Haskell function composition +
+ +

Forget glitches because of undefined.

+
+
+

Haskell Kinds

+

In Haskell some types can take type variable(s). Typically: [a].

+

Types have kinds; The kind is to type what type is to function. Kind are the types for types (so meta).

+
Int, Char :: *
+[], Maybe :: * -> *
+(,), (->) :: * -> * -> *
+[Int], Maybe Char, Maybe [Int] :: *
+
+
+

Haskell Types

+

Sometimes, the type determine a lot about the function:

+
fst :: (a,b) -> a -- Only one choice
+snd :: (a,b) -> b -- Only one choice
+f :: a -> [a]     -- Many choices
+-- Possibilities: f x=[], or [x], or [x,x] or [x,...,x]
+
+? :: [a] -> [a] -- Many choices
+-- can only rearrange: duplicate/remove/reorder elements
+-- for example: the type of addOne isn't [a] -> [a]
+addOne l = map (+1) l
+-- The (+1) force 'a' to be a Num.
+ +

+

★:Theorems for free!, Philip Wadler, 1989

+
+
+

Haskell Functor vs \(\Hask\) Functor

+ +

A Haskell Functor is a type F :: * -> * which belong to the type class Functor ; thus instantiate +fmap :: (a -> b) -> (F a -> F b). + +

& F: \(\ob{\Hask}→\ob{\Hask}\)
& fmap: \(\hom{\Hask}→\hom{\Hask}\) + +

The couple (F,fmap) is a \(\Hask\)'s functor if for any x :: F a:

+
  • fmap id x = x +
  • fmap (f.g) x= (fmap f . fmap g) x +
+
+
+

Haskell Functors Example: Maybe

+ +
data Maybe a = Just a | Nothing
+instance Functor Maybe where
+    fmap :: (a -> b) -> (Maybe a -> Maybe b)
+    fmap f (Just a) = Just (f a)
+    fmap f Nothing = Nothing
+
fmap (+1) (Just 1) == Just 2
+fmap (+1) Nothing  == Nothing
+fmap head (Just [1,2,3]) == Just 1
+
+
+

Haskell Functors Example: List

+ +
instance Functor ([]) where
+	fmap :: (a -> b) -> [a] -> [b]
+	fmap = map
+
fmap (+1) [1,2,3]           == [2,3,4]
+fmap (+1) []                == []
+fmap head [[1,2,3],[4,5,6]] == [1,4]
+
+
+

Haskell Functors for the programmer

+

Functor is a type class used for types that can be mapped over.

+
    +
  • Containers: [], Trees, Map, HashMap...
  • +
  • "Feature Type": +
      +
    • Maybe a: help to handle absence of a.
      Ex: safeDiv x 0 ⇒ Nothing
    • +
    • Either String a: help to handle errors
      Ex: reportDiv x 0 ⇒ Left "Division by 0!"
    • +
  • +
+
+
+

Haskell Functor intuition

+ +

Put normal function inside a container. Ex: list, trees...

+ +Haskell Functor as a box play +

+
+

Haskell Functor properties

+ +

Haskell Functors are:

+ +
  • endofunctors ; \(F:\C→\C\) here \(\C = \Hask\), +
  • a couple (Object,Morphism) in \(\Hask\). +
+
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

Functor as boxes

+ +

Haskell functor can be seen as boxes containing all Haskell types and functions. +Haskell types is fractal:

+ +Haskell functor representation +
+
+

"Non Haskell" Hask's Functors

+

A simple basic example is the \(id_\Hask\) functor. It simply cannot be expressed as a couple (F,fmap) where

+
    +
  • F::* -> *
  • +
  • fmap :: (a -> b) -> (F a) -> (F b)
  • +
+

Another example:

+
    +
  • F(T)=Int
  • +
  • F(f)=\_->0
  • +
+
+
+

Also Functor inside \(\Hask\)

+

\(\mathtt{[a]}∈\ob{\Hask}\) but is also a category. Idem for Int.

+

length is a Functor from the category [a] to the cateogry Int:

+
    +
  • \(\ob{\mathtt{[a]}}=\{∙\}\)
  • +
  • \(\hom{\mathtt{[a]}}=\mathtt{[a]}\)
  • +
  • \(∘=\mathtt{(++)}\)
  • +
+

+
    +
  • \(\ob{\mathtt{Int}}=\{∙\}\)
  • +
  • \(\hom{\mathtt{Int}}=\mathtt{Int}\)
  • +
  • \(∘=\mathtt{(+)}\)
  • +
+
+
  • id: length [] = 0 +
  • comp: length (l ++ l') = (length l) + (length l') +
+
+
+

Category of \(\Hask\) Endofunctors

+Category of Hask endofunctors +
+
+

Category of Functors

+

If \(\C\) is small (\(\hom{\C}\) is a set). All functors from \(\C\) to some category \(\D\) form the category \(\mathrm{Func}(\C,\D)\).

+
    +
  • \(\ob{\mathrm{Func}(\C,\D)}\): Functors \(F:\C→\D\)
  • +
  • \(\hom{\mathrm{Func}(\C,\D)}\): natural transformations
  • +
  • ∘: Functor composition
  • +
+

\(\mathrm{Func}(\C,\C)\) is the category of endofunctors of \(\C\).

+
+
+

Natural Transformations

+

Let \(F\) and \(G\) be two functors from \(\C\) to \(\D\).

+

Natural transformation commutative diagram A natural transformation: familly η ; \(η_X\in\hom{\D}\) for \(X\in\ob{\C}\) s.t.

+

ex: between Haskell functors; F a -> G a
Rearragement functions only.

+
+
+

Natural Transformation Examples (1/4)

+
data Tree a = Empty | Node a [Tree a]
+toTree :: [a] -> Tree a
+toTree [] = Empty
+toTree (x:xs) = Node x [toTree xs]
+ +

toTree is a natural transformation. It is also a morphism from [] to Tree in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram +
+ + +
+
+

Natural Transformation Examples (2/4)

+
data Tree a = Empty | Node a [Tree a]
+toList :: Tree a -> [a]
+toList Empty = []
+toList (Node x l) = [x] ++ concat (map toList l)
+ +

toList is a natural transformation. It is also a morphism from Tree to [] in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram
toList . toTree = id & toTree . toList = id &
therefore [] & Tree are isomorph.
+
+ + +
+
+

Natural Transformation Examples (3/4)

+
toMaybe :: [a] -> Maybe a
+toMaybe [] = Nothing
+toMaybe (x:xs) = Just x
+ +

toMaybe is a natural transformation. It is also a morphism from [] to Maybe in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+natural transformation commutative diagram +
+ + +
+
+

Natural Transformation Examples (4/4)

+
mToList :: Maybe a -> [a]
+mToList Nothing = []
+mToList Just x  = [x]
+ +

toMaybe is a natural transformation. It is also a morphism from [] to Maybe in the Category of \(\Hask\) endofunctors.

+natural transformation commutative diagram +
+relation between [] and Maybe
There is no isomorphism.
Hint: Bool lists longer than 1.
+
+ + +
+
+

Composition problem

+

The Problem; example with lists:

+
f x = [x]       ⇒ f 1 = [1]   ⇒ (f.f) 1 = [[1]] ✗
+g x = [x+1]     ⇒ g 1 = [2]   ⇒ (g.g) 1 = ERROR [2]+1 ✗
+h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h.h) 1 = ERROR [2,3]+1 ✗ 
+ +

The same problem with most f :: a -> F a functions and functor F.

+
+
+

Composition Fixable?

+

How to fix that? We want to construct an operator which is able to compose:

+

f :: a -> F b & g :: b -> F c.

+

More specifically we want to create an operator ◎ of type

+

◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)

+

Note: if F = I, ◎ = (.).

+
+
+

Fix Composition (1/2)

+

Goal, find: ◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)
f :: a -> F b, g :: b -> F c:

+
    +
  • (g ◎ f) x ???
  • +
  • First apply f to xf x :: F b
  • +
  • Then how to apply g properly to an element of type F b?
  • +
+
+
+

Fix Composition (2/2)

+

Goal, find: ◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)
f :: a -> F b, g :: b -> F c, f x :: F b:

+
    +
  • Use fmap :: (t -> u) -> (F t -> F u)!
  • +
  • (fmap g) :: F b -> F (F c) ; (t=b, u=F c)
  • +
  • (fmap g) (f x) :: F (F c) it almost WORKS!
  • +
  • We lack an important component, join :: F (F c) -> F c
  • +
  • (g ◎ f) x = join ((fmap g) (f x))
    ◎ is the Kleisli composition; in Haskell: <=< (in Control.Monad).
  • +
+
+
+

Necessary laws

+

For ◎ to work like composition, we need join to hold the following properties:

+
    +
  • join (join (F (F (F a))))=join (F (join (F (F a))))
  • +
  • abusing notations denoting join by ⊙; this is equivalent to
    (F ⊙ F) ⊙ F = F ⊙ (F ⊙ F)
  • +
  • There exists η :: a -> F a s.t.
    η⊙F=F=F⊙η
  • +
+
+
+

Klesli composition

+

Now the composition works as expected. In Haskell ◎ is <=< in Control.Monad.

+

g <=< f = \x -> join ((fmap g) (f x))

+
f x = [x]       ⇒ f 1 = [1]   ⇒ (f <=< f) 1 = [1] ✓
+g x = [x+1]     ⇒ g 1 = [2]   ⇒ (g <=< g) 1 = [3] ✓
+h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h <=< h) 1 = [3,6,4,9] ✓
+ + +
+
+

We reinvented Monads!

+

A monad is a triplet (M,⊙,η) where

+
    +
  • \(M\) an Endofunctor (to type a associate M a)
  • +
  • \(⊙:M×M→M\) a nat. trans. (i.e. ⊙::M (M a) → M a ; join)
  • +
  • \(η:I→M\) a nat. trans. (\(I\) identity functor ; η::a → M a)
  • +
+

Satisfying

+
    +
  • \(M ⊙ (M ⊙ M) = (M ⊙ M) ⊙ M\)
  • +
  • \(η ⊙ M = M = M ⊙ η\)
  • +
+
+
+

Compare with Monoid

+

A Monoid is a triplet \((E,∙,e)\) s.t.

+
    +
  • \(E\) a set
  • +
  • \(∙:E×E→E\)
  • +
  • \(e:1→E\)
  • +
+

Satisfying

+
    +
  • \(x∙(y∙z) = (x∙y)∙z, ∀x,y,z∈E\)
  • +
  • \(e∙x = x = x∙e, ∀x∈E\)
  • +
+
+
+

Monads are just Monoids

+
+

A Monad is just a monoid in the category of endofunctors, what's the problem?

+
+

The real sentence was:

+
+

All told, a monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor.

+
+
+
+

Example: List

+
    +
  • [] :: * -> * an Endofunctor
  • +
  • \(⊙:M×M→M\) a nat. trans. (join :: M (M a) -> M a)
  • +
  • \(η:I→M\) a nat. trans.
  • +
+
-- In Haskell ⊙ is "join" in "Control.Monad"
+join :: [[a]] -> [a]
+join = concat
+
+-- In Haskell the "return" function (unfortunate name)
+η :: a -> [a]
+η x = [x]
+ + +
+
+

Example: List (law verification)

+

Example: List is a functor (join is ⊙)

+
    +
  • \(M ⊙ (M ⊙ M) = (M ⊙ M) ⊙ M\)
  • +
  • \(η ⊙ M = M = M ⊙ η\)
  • +
+
join [ join [[x,y,...,z]] ] = join [[x,y,...,z]]
+                            = join (join [[[x,y,...,z]]])
+join (η [x]) = [x] = join [η x]
+ +

Therefore ([],join,η) is a monad.

+
+
+

Monads useful?

+

A LOT of monad tutorial on the net. Just one example; the State Monad

+

DrawScene to State Screen DrawScene ; still pure.

+
main = drawImage (width,height)
+
+drawImage :: Screen -> DrawScene
+drawImage screen = do
+    drawPoint p screen
+    drawCircle c screen
+    drawRectangle r screen
+
+drawPoint point screen = ...
+drawCircle circle screen = ...
+drawRectangle rectangle screen = ...
+
main = do
+    put (Screen 1024 768)
+    drawImage
+
+drawImage :: State Screen DrawScene
+drawImage = do
+    drawPoint p
+    drawCircle c
+    drawRectangle r
+
+drawPoint :: Point -> State Screen DrawScene
+drawPoint p = do
+    Screen width height <- get
+    ...
+
+
+

fold

+fold +
+
+

κατα-morphism

+catamorphism +
+
+

κατα-morphism: fold generalization

+

acc type of the "accumulator":
fold :: (acc -> a -> acc) -> acc -> [a] -> acc

+

Idea: put the accumulated value inside the type.

+
-- Equivalent to fold (+1) 0 "cata"
+(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' Nil))))
+(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' 0))))
+(Cons 'c' (Cons 'a' (Cons 't' 1)))
+(Cons 'c' (Cons 'a' 2))
+(Cons 'c' 3)
+4
+ + +

But where are all the informations? (+1) and 0?

+
+
+

κατα-morphism: Missing Information

+

Where is the missing information?

+
    +
  • Functor operator fmap
  • +
  • Algebra representing the (+1) and also knowing about the 0.
  • +
+

First example, make length on [Char]

+
+
+

κατα-morphism: Type work

+

+data StrF a = Cons Char a | Nil
+data Str' = StrF Str'
+
+-- generalize the construction of Str to other datatype
+-- Mu: type fixed point
+-- Mu :: (* -> *) -> *
+
+data Mu f = InF { outF :: f (Mu f) }
+data Str = Mu StrF
+
+-- Example
+foo=InF { outF = Cons 'f'
+        (InF { outF = Cons 'o'
+            (InF { outF = Cons 'o'
+                (InF { outF = Nil })})})}
+ + +
+
+

κατα-morphism: missing information retrieved

+
type Algebra f a = f a -> a
+instance Functor (StrF a) =
+    fmap f (Cons c x) = Cons c (f x)
+    fmap _ Nil = Nil
+ +
cata :: Functor f => Algebra f a -> Mu f -> a
+cata f = f . fmap (cata f) . outF
+ + + +
+
+

κατα-morphism: Finally length

+

All needed information for making length.

+
instance Functor (StrF a) =
+    fmap f (Cons c x) = Cons c (f x)
+    fmap _ Nil = Nil
+
+length' :: Str -> Int
+length' = cata phi where
+    phi :: Algebra StrF Int -- StrF Int -> Int
+    phi (Cons a b) = 1 + b
+    phi Nil = 0
+
+main = do
+    l <- length' $ stringToStr "Toto"
+    ...
+
+
+

κατα-morphism: extension to Trees

+

Once you get the trick, it is easy to extent to most Functor.

+
type Tree = Mu TreeF
+data TreeF x = Node Int [x]
+
+instance Functor TreeF where
+  fmap f (Node e xs) = Node e (fmap f xs)
+
+depth = cata phi where
+  phi :: Algebra TreeF Int -- TreeF Int -> Int
+  phi (Node x sons) = 1 + foldr max 0 sons
+
+
+

Conclusion

+

Category Theory oriented Programming:

+
    +
  • Focus on the type and operators
  • +
  • Extreme generalisation
  • +
  • Better modularity
  • +
  • Better control through properties of types
  • +
+

No cat were harmed in the making of this presentation.

+
diff --git a/output/Scratch/assets/css/main.css b/output/Scratch/assets/css/main.css index f22568388..522b80a64 100644 --- a/output/Scratch/assets/css/main.css +++ b/output/Scratch/assets/css/main.css @@ -1 +1 @@ -@font-face{font-family:"cmuntt";src:url("fonts/cmuntt.eot");src:local("☺"),url("fonts/cmuntt.svg") format("svg"),url("fonts/cmuntt.ttf") format("truetype");font-weight:400;font-style:normal}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrb.eot");src:local("☺"),url("fonts/cmunrb.svg") format("svg"),url("fonts/cmunrb.ttf") format("truetype");font-weight:700}@font-face{font-family:"ComputerModern";src:url("fonts/cmunsl.eot");src:local("☺"),url("fonts/cmunsl.svg") format("svg"),url("fonts/cmunsl.ttf") format("truetype");font-style:italic,oblique}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrm.eot");src:local("☺"),url("fonts/cmunrm.svg") format("svg"),url("fonts/cmunrm.ttf") format("truetype");font-weight:400;font-style:normal}i,em{font-style:italic}b,strong,h1,h2,h3,h4,h5,h6{font-weight:700}table.description tr td{border:1px solid #eeeef1}.assombris20{background-color:#eeeef1}body{color:#002b36;background-color:#fafafc}::selection{background:#002b36;color:#93a1a1}::-moz-selection{background:#002b36;color:#93a1a1}pre,code,a.cut{font-family:"cmuntt",Incosolata,Monaco,monospace}pre::selection{background:#fdf6e3;color:#586e75}pre *::selection{background:#fdf6e3;color:#586e75}pre::-moz-selection{background:#fdf6e3;color:#586e75}pre *::-moz-selection{background:#fdf6e3;color:#586e75}a:hover{text-shadow:0 0 2px#faa}a,a:link,a:visited,a:active,a:hover{text-decoration:none;outline:none}a,a:link,a:visited,a:active{color:#002b36}a:hover{color:#cb4b16}hr{color:#eeeef1;border-top:1px solid #eeeef1;border-bottom:none;border-left:none;border-right:none}ul{list-style:none}.corps ul li:before{content:"- "}ol,ul{padding-left:0}.toc ol li,.toc ul li{margin:.5em 0}ol li ul,ol li ol,ul li ol,ul li ul{margin:.5em 1.5em;list-style:none}body,h1,h2,h3,h4,#entete,.tagname{text-rendering:optimizelegibility;line-height:1.5em}body{font-family:"ComputerModern",Georgia,Palatino,"Century Schoolbook L","Times New Roman",Times,serif}.article #afterheader{counter-reset:niv02}.article #afterheader h2{counter-increment:niv02;counter-reset:niv03;marker-offset:3em}.article #afterheader h2:before{content:counter(niv02) ". "}.article #afterheader h3{counter-increment:niv03;counter-reset:niv04}.article #afterheader h3:before{content:counter(niv02) "." counter(niv03) ". "}.article #afterheader h4{counter-increment:niv04}.article #afterheader h4:before{content:counter(niv02) "." counter(niv03) "." counter(niv04) ". "}pre{background-color:#002b36;color:#839496;box-shadow:0 0 5px #d0d0d2 inset;border-radius:3px;padding:1em;line-height:1em;font-size:.9em}p{margin-bottom:1.2em}blockquote{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;font-style:italic;padding:.5em 1em;color:#556}blockquote a:hover{color:#cb4b16}blockquote i,blockquote em{font-weight:400;font-style:normal;color:#002b36}blockquote strong,blockquote b{font-weight:700;color:#002b36}blockquote ul{padding-left:1.5em}abbr,acronym{text-transform:uppercase;font-size:.8em;text-decoration:none;border-bottom-width:0}#titre{letter-spacing:-0.06em;border-bottom:4px double #ccccd0;border-top:4px double #ccccd0}#liens .active,#sousliens{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}#liens .active a,#sousliens a{color:#667}#liens .active a:hover,#sousliens a:hover{color:#cb4b16}#liens .active a:hover strong,#liens .active a:hover b,#liens .active a:hover i,#liens .active a:hover em,#liens .active a:hover .nicer,#sousliens a:hover strong,#sousliens a:hover b,#sousliens a:hover i,#sousliens a:hover em,#sousliens a:hover .nicer{color:#ffb17c}#liens .active hr,#sousliens hr{color:#667;border-top:1px solid#667}#liens .active strong,#liens .active b,#liens .active i,#liens .active em,#sousliens strong,#sousliens b,#sousliens i,#sousliens em{color:#002b36}#liens a{border:1px solid#eee;background:rgba(0,0,0,0.05);box-shadow:0 0 2px white,0 0 3px#ccc inset;border:1px solid rgba(0,0,0,0.1);border-radius:3px}#liens a:hover{background:rgba(0,0,0,0.1);box-shadow:0 0 6px#555 inset}#liens .active{text-shadow:0 0 2px rgba(0,0,0,0.5);background-color:#f7f7f9;border:1px solid #e9e9eb;box-shadow:0 0 3px #c7c7c9 inset;border-radius:3px;border-top:none}#lastmod{font-size:.9em}.nojsbutton{font-size:2.5em}#clickcomment,#choixlang > a,#choixrss > a,.return > a{display:block;width:25%;cursor:pointer;margin:1em 0;padding:1em;font-size:16px;line-height:1.4em;border:1px solid #fafafc;color:#ccccd0}#clickcomment:hover,#choixlang > a:hover,#choixrss > a:hover,.return > a:hover{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px#faa}#clickcomment:active,#choixlang > a:active,#choixrss > a:active,.return > a:active{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px#faa;background:#f4f4f6}.return > a,#choixrss > a{float:right}#choix .return > a,#choix #choixrss > a{margin-top:0}.small{font-size:.8em}.sc{text-transform:uppercase;font-size:.8em}.impact,.darkimpact{font-size:2em;margin:0 auto 1em auto;line-height:1.3em}h1 > .date{font-size:.6em;color:#002b36}.date{font-size:.8em;color:#fafafc;border:1px solid #002b36;text-align:center;width:4.1em;line-height:1.5em;display:inline-block;vertical-align:middle;margin-right:1em}.date .day,.date .month,.date .year{display:block}.date .day{color:#002b36;background-color:#fafafc;float:left;width:1.7em}.date .month{float:right;width:2.3em;background-color:#002b36;color:#fafafc}.date .year{line-height:3ex;clear:both;color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1;border-radius:0}.date .year a{color:#667}.date .year a:hover{color:#cb4b16}.date .year a:hover strong,.date .year a:hover b,.date .year a:hover i,.date .year a:hover em,.date .year a:hover .nicer{color:#ffb17c}.date .year hr{color:#667;border-top:1px solid#667}.date .year strong,.date .year b,.date .year i,.date .year em{color:#002b36}body{text-align:center;font-size:16px}body > #entete{position:absolute;left:0;top:.5em;width:100%;min-width:50em;z-index:8000;padding-bottom:1em;margin-bottom:3em}#titre h2{width:80%;margin-left:auto;margin-right:auto;text-align:center;color:#ccccd0}#titre{text-align:center;width:100%}#titre h1,#titre h2{padding-left:1em;padding-right:1em}#bottom{clear:right;margin-right:0;padding:1.5em;line-height:1.5em;color:#224d58;margin-top:2em;text-align:center}#bottom a{color:#113c47}#bottom a:hover{color:#cb4b16}#sousliens{padding:1em 0;line-height:2em}#sousliens ul{list-style:none;margin-left:4em}ul.horizontal li{display:inline;font-size:.9em}ul.horizontal{margin-top:0;margin-bottom:0}#entete{padding-top:.1em;border-top:1px solid #ccccd0;border-bottom:1px solid #ccccd0}#liens{width:100%;padding:0;clear:both;margin-top:.5em}#liens ul{width:100%;clear:both;padding:0;margin:0}#liens ul li{display:inline-block;height:4em;margin-left:.2em;margin-right:.2em;width:23%}#liens ul li a,#liens ul li span{width:100%;display:block;line-height:4em}.clear{clear:both}#content{line-height:4em;margin-left:auto;margin-right:auto;margin-top:0;position:relative;clear:both;width:52em}.encadre,.black,.red,.intro,.resume,.shadow{padding:2em;margin-top:2em;margin-bottom:2em}.encadre,.black,.red,.shadow{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}.encadre a,.black a,.red a,.shadow a{color:#667}.encadre a:hover,.black a:hover,.red a:hover,.shadow a:hover{color:#cb4b16}.encadre a:hover strong,.encadre a:hover b,.encadre a:hover i,.encadre a:hover em,.encadre a:hover .nicer,.black a:hover strong,.black a:hover b,.black a:hover i,.black a:hover em,.black a:hover .nicer,.red a:hover strong,.red a:hover b,.red a:hover i,.red a:hover em,.red a:hover .nicer,.shadow a:hover strong,.shadow a:hover b,.shadow a:hover i,.shadow a:hover em,.shadow a:hover .nicer{color:#ffb17c}.encadre hr,.black hr,.red hr,.shadow hr{color:#667;border-top:1px solid#667}.encadre strong,.encadre b,.encadre i,.encadre em,.black strong,.black b,.black i,.black em,.red strong,.red b,.red i,.red em,.shadow strong,.shadow b,.shadow i,.shadow em{color:#002b36}pre .red{background:none;padding:0;margin:auto;border:none;box-shadow:none}.intro,.resume{font-size:.9em;font-style:italic;padding:.5em 1em;color:#556}.intro a:hover,.resume a:hover{color:#cb4b16}.intro i,.intro em,.resume i,.resume em{font-weight:400;font-style:normal;color:#002b36}.intro strong,.intro b,.resume strong,.resume b{font-weight:700;color:#002b36}#afterheader > h1{width:100%;padding-top:1.5em;text-align:left}#afterheader{padding-left:0;padding-right:0}#sousliens{margin-top:3em;margin-bottom:3em;font-size:1.2em;letter-spacing:1px;text-align:left;clear:both}.twilight{line-height:1.1em}.corps{font-size:1.25em;line-height:1.5em;text-align:justify;padding:3em 3em;margin:0;clear:both}.corps p,.corps ol,.corps ul,.corps blockquote,.corps pre,.corps code{margin-top:1.5em;margin-bottom:1.5em}.corps pre code{margin:0}.corps p,.corps ol,.corps ul,.corps blockquote{line-height:1.5em}.corps pre,.corps code{line-height:1em}.corps ul li ul,.corps ol li ul,.corps ul li ol,.corps ol li ol{margin-top:0;margin-bottom:0}.corps img{max-width:80%;border:1px solid #ccccd0;background-color:#fafafc;padding:.5em;box-shadow:0 10px 15px#ccc;border-radius:3px}.corps a:hover img{background-color:#dc3a05}figure{margin:3em 0}figure img{box-shadow:0 10px 15px#ccc inset}figure figcaption{text-align:center;margin:.5em 0}img.clean{border:none;background-color:none;box-shadow:none}#address{clear:both}.definitionCell{width:5em;vertical-align:top;text-align:center;font-weight:700}.valueCell{text-align:right}.smallblock{float:left;width:50%;font-size:1em;font-weight:700}.largeblock{float:right;width:70%;font-size:1em}#blackpage,#nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:absolute;text-align:center}#blackpage{color:#002b36;background-color:#fafafc;font-family:Georgia,serif;font-style:italic;padding-top:8em;z-index:9000;cursor:wait}#blackpage .corps code,#blackpage .corps pre{font-family:monospace}#blackpage img{background:none;border:none;max-width:80%;margin:0 auto}#blackpage a{cursor:pointer}#blackpage .preh1{font-size:1.5em;font-weight:700;margin-bottom:1em}#blackpage .preh2{font-size:1.2em;font-style:italic;margin-bottom:1em}#blackpage .preintro{text-align:left;width:52em;margin:0 auto}#nojsredirect{z-index:9001}.nojsbutton{width:50%;padding:1em;border:solid 3px white;margin-left:auto;margin-right:auto;margin-top:2em;z-index:9002}.codefile{font-size:.8em;text-align:right;padding-right:1em;margin-right:.1;margin-bottom:-1em}.flush{clear:both}table.description{border-spacing:5px;border-collapse:separate;margin-right:auto;margin-left:auto}table.description tr td{padding-left:.5em;padding-right:.5em;padding-top:.5ex;padding-bottom:.5ex;vertical-align:middle;margin-right:5px}ul.long li{margin-bottom:1em}img{display:block;margin:1.2em auto;background:none;border:none}img.left{float:left;max-width:30%;margin-top:.6em;margin-right:2em}img.inside{display:inline;vertical-align:middle}pre{overflow-x:auto;overflow-y:hidden}.navigationprev,.navigationnext{padding:0;margin-left:.2em;margin-right:.2em;margin-bottom:0;margin-top:3em;width:45%}.navigation .navigationprev,.navigation .navigationnext{width:30%;margin-top:0}.navigation{height:4em;border-bottom:#ccccd0 solid 1px}.presarticleleft,.presarticleright{font-size:1em}.navigationprev{float:left;text-align:left}.navigationnext{float:right;text-align:right}.impact,.darkimpact{text-align:left;width:66%;padding-left:.25em;padding-right:.25em}table.impact{text-align:left}table.impact tr td{padding-left:.25em;padding-right:.25em}#liens{font-size:1.2em}#iemessage{font-size:1.2em;color:#ccc;margin:-10px;padding:1px 0;background:#333}#iemessage strong,#iemessage b,#iemessage i,#iemessage em{color:#ccc}#iemessage a,#iemessage a:visited{color:#eca}.tagname{display:inline;cursor:pointer;margin-left:.5em;margin-right:.5em}.list{margin-top:3em}#menuMessage{font-size:1.2em;line-height:1.5em;width:100%;text-align:center}#next_before_articles{clear:both;width:100%;font-size:1.2em;padding-top:1em;padding-bottom:1em}#previous_articles,#next_articles{color:#889;font-size:.8em;font-style:italic}#previous_articles{float:left;margin-left:1em;width:45%;text-align:left}.previous_article,.next_article{margin-top:1em}#next_articles{float:right;width:45%;margin-right:1em;text-align:right}#rss{font-size:1.2em;text-align:center;display:block;width:100%;float:right;padding:1em .1em}.corps .return a{color:#eeeef1;padding:.1em;line-height:1.5em;font-size:1.5em;height:1.5em;float:left;font-size:2em;margin-top:-0.5em;margin-left:-2em;width:1.5em}a.return{color:#eeeef1;padding:.1em;line-height:1.5em;font-size:1.5em;height:1.5em;font-size:2em;width:1.5em;display:block}a.return:hover{color:#889}.corps .return a:hover{color:#cb4b16}.footnotes{font-size:.8em}.footnotes ol{color:#839496;font-weight:700}.footnotes ol p{color:#002b36;font-weight:400;font-style:normal}.fontnotes ol{margin-left:0}.typeset img{display:inline;border:none;margin:0;padding:0}strong,b,i,em{color:#889}strong a,b a,i a,em a{color:#002b36}strong a:hover,b a:hover,i a:hover,em a:hover{color:#cb4b16}.corps p strong,.corps p b,.corps p i,.corps p em{color:#556}a:hover strong,a:hover b,a:hover i,a:hover em{color:#dc5c27}a:hover .nicer{color:#ffb17c}.nicer{color:#ccccd0;font-family:"Lucida Grande",Tahoma}.block{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;width:26.5%;padding:1em;border-radius:2px;text-align:left;line-height:1em;margin-left:1%;margin-right:1%;font-size:.8em;height:9em}.block a{color:#002b36}.block a:hover{color:#cb4b16}.block h3{margin:0;font-size:1.3em}.block p{line-height:1.2em}.left{float:left}.right{float:right}.corps p a,.corps ul a{color:#556}.corps p a:hover,.corps ul a:hover{color:#cb4b16}ul.bloglist,.archive ul{list-style-type:none;margin:0}ul.bloglist li,.archive ul li{margin-bottom:1em}.button{cursor:pointer;text-align:center}#tagcloud{font-size:.8em;background:#f2f2f4;box-shadow:0 0 6px #ccccd0;border-radius:3px;line-height:2.5em;padding:2em;text-align:justify}.pala{font-family:Palatino}sup{vertical-align:top;font-size:.7em}.article .corps a:after{content:"†";vertical-align:super;line-height:0;font-size:.66em;color:#889}.article .corps .footnotes a:after,.article .corps sup a:after{content:""}.article .corps sup a{font-weight:700;padding:0 .3em;margin-left:2px;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}.article .corps sup a:hover{color:#cb4b16}ul#markdown-toc,.intro .toc ul{text-transform:uppercase;font-size:.8em;list-style:none;padding-left:1.5em}ul#markdown-toc a:after,.intro .toc ul a:after{content:""}ul#markdown-toc ul ul,.intro .toc ul ul ul{font-variant:normal;line-height:1em;font-size:1em;margin-bottom:1em}table{border:1px solid #ccccd0}table tr td{padding:2px .5em}table tr:nth-child(odd){background-color:#f2f2f4}table tr:nth-child(even){background-color:#fafafc}p pre code,ul li pre code,ol li pre code{background:none;border:none;padding:0}p code,ul li code,ol li code{background:#f0f0f2;border:solid 1px #ccccd0;padding:2px}ul.sameline{list-style:none}ul.sameline li{float:left;margin-left:.5em}.resumearticle{background-color:#f2f2f4;border-radius:7px;box-shadow:0 0 5px #c7c7b8 inset,0 0 5px white;margin:1em 0;padding:1em}a.cut{font-size:12px;text-align:right;display:block;width:100%;opacity:.5;border:1px solid #fafafc;border-radius:3px}a.cut:hover{opacity:1;background-color:#f2f2f4;border-color:#ccccd0;box-shadow:0 0 3px #ccccd0 inset}a.cut strong{font-weight:700}.codehighlight pre{border-left:4px solid #ccccd0}#social{text-align:left;opacity:.3}#social:hover{opacity:1}.popularblock{width:30.3333%;margin:0 1.5%;float:left}.popularblock figure{margin:0}.popularblock figure img{max-width:80%;max-height:6em} \ No newline at end of file +@font-face{font-family:"cmuntt";src:url("fonts/cmuntt.eot");src:local("☺"),url("fonts/cmuntt.svg") format("svg"),url("fonts/cmuntt.ttf") format("truetype");font-weight:400;font-style:normal}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrb.eot");src:local("☺"),url("fonts/cmunrb.svg") format("svg"),url("fonts/cmunrb.ttf") format("truetype");font-weight:700}@font-face{font-family:"ComputerModern";src:url("fonts/cmunsl.eot");src:local("☺"),url("fonts/cmunsl.svg") format("svg"),url("fonts/cmunsl.ttf") format("truetype");font-style:italic,oblique}@font-face{font-family:"ComputerModern";src:url("fonts/cmunrm.eot");src:local("☺"),url("fonts/cmunrm.svg") format("svg"),url("fonts/cmunrm.ttf") format("truetype");font-weight:400;font-style:normal}i,em{font-style:italic}b,strong,h1,h2,h3,h4,h5,h6{font-weight:700}table.description tr td{border:1px solid #eeeef1}.assombris20{background-color:#eeeef1}body{color:#002b36;background-color:#fafafc}::selection{background:#002b36;color:#93a1a1}::-moz-selection{background:#002b36;color:#93a1a1}pre,code,a.cut{font-family:"cmuntt",Incosolata,Monaco,monospace}pre::selection{background:#fdf6e3;color:#586e75}pre *::selection{background:#fdf6e3;color:#586e75}pre::-moz-selection{background:#fdf6e3;color:#586e75}pre *::-moz-selection{background:#fdf6e3;color:#586e75}a:hover{text-shadow:0 0 2px#faa}a,a:link,a:visited,a:active,a:hover{text-decoration:none;outline:none}a,a:link,a:visited,a:active{color:#002b36}a:hover{color:#cb4b16}hr{color:#eeeef1;border-top:1px solid #eeeef1;border-bottom:none;border-left:none;border-right:none}ul{list-style:none}.corps ul li:before{content:"- "}ol,ul{padding-left:0}.toc ol li,.toc ul li{margin:.5em 0}ol li ul,ol li ol,ul li ol,ul li ul{margin:.5em 1.5em;list-style:none}body,h1,h2,h3,h4,#entete,.tagname{text-rendering:optimizelegibility;line-height:1.5em}body{font-family:"ComputerModern",Georgia,Palatino,"Century Schoolbook L","Times New Roman",Times,serif}.article #afterheader{counter-reset:niv02}.article #afterheader h2{counter-increment:niv02;counter-reset:niv03;marker-offset:3em}.article #afterheader h2:before{content:counter(niv02) ". "}.article #afterheader h3{counter-increment:niv03;counter-reset:niv04}.article #afterheader h3:before{content:counter(niv02) "." counter(niv03) ". "}.article #afterheader h4{counter-increment:niv04}.article #afterheader h4:before{content:counter(niv02) "." counter(niv03) "." counter(niv04) ". "}pre{background-color:#002b36;color:#839496;box-shadow:0 0 5px #d0d0d2 inset;border-radius:3px;padding:1em;line-height:1em;font-size:.9em}p{margin-bottom:1.2em}blockquote{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;font-style:italic;padding:.5em 1em;color:#556}blockquote a:hover{color:#cb4b16}blockquote i,blockquote em{font-weight:400;font-style:normal;color:#002b36}blockquote strong,blockquote b{font-weight:700;color:#002b36}blockquote ul{padding-left:1.5em}abbr,acronym{text-transform:uppercase;font-size:.8em;text-decoration:none;border-bottom-width:0}#titre{letter-spacing:-0.06em;border-bottom:4px double #ccccd0;border-top:4px double #ccccd0}#liens .active,#sousliens{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}#liens .active a,#sousliens a{color:#667}#liens .active a:hover,#sousliens a:hover{color:#cb4b16}#liens .active a:hover strong,#liens .active a:hover b,#liens .active a:hover i,#liens .active a:hover em,#liens .active a:hover .nicer,#sousliens a:hover strong,#sousliens a:hover b,#sousliens a:hover i,#sousliens a:hover em,#sousliens a:hover .nicer{color:#ffb17c}#liens .active hr,#sousliens hr{color:#667;border-top:1px solid#667}#liens .active strong,#liens .active b,#liens .active i,#liens .active em,#sousliens strong,#sousliens b,#sousliens i,#sousliens em{color:#002b36}#liens a{border:1px solid#eee;background:rgba(0,0,0,0.05);box-shadow:0 0 2px white,0 0 3px#ccc inset;border:1px solid rgba(0,0,0,0.1);border-radius:3px}#liens a:hover{background:rgba(0,0,0,0.1);box-shadow:0 0 6px#555 inset}#liens .active{text-shadow:0 0 2px rgba(0,0,0,0.5);background-color:#f7f7f9;border:1px solid #e9e9eb;box-shadow:0 0 3px #c7c7c9 inset;border-radius:3px;border-top:none}#lastmod{font-size:.9em}.nojsbutton{font-size:2.5em}#clickcomment,#choixlang > a,#choixrss > a,.return > a{display:block;width:25%;cursor:pointer;margin:1em 0;padding:1em;font-size:16px;line-height:1.4em;border:1px solid #fafafc;color:#ccccd0}#clickcomment:hover,#choixlang > a:hover,#choixrss > a:hover,.return > a:hover{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px#faa}#clickcomment:active,#choixlang > a:active,#choixrss > a:active,.return > a:active{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;color:#dc5c27;text-shadow:0 0 2px#faa;background:#f4f4f6}.return > a,#choixrss > a{float:right}#choix .return > a,#choix #choixrss > a{margin-top:0}.small{font-size:.8em}.sc{text-transform:uppercase;font-size:.8em}.impact,.darkimpact{font-size:2em;margin:0 auto 1em auto;line-height:1.3em}h1 > .date{font-size:.6em;color:#002b36}.date{font-size:.8em;color:#fafafc;border:1px solid #002b36;text-align:center;width:4.1em;line-height:1.5em;display:inline-block;vertical-align:middle;margin-right:1em}.date .day,.date .month,.date .year{display:block}.date .day{color:#002b36;background-color:#fafafc;float:left;width:1.7em}.date .month{float:right;width:2.3em;background-color:#002b36;color:#fafafc}.date .year{line-height:3ex;clear:both;color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1;border-radius:0}.date .year a{color:#667}.date .year a:hover{color:#cb4b16}.date .year a:hover strong,.date .year a:hover b,.date .year a:hover i,.date .year a:hover em,.date .year a:hover .nicer{color:#ffb17c}.date .year hr{color:#667;border-top:1px solid#667}.date .year strong,.date .year b,.date .year i,.date .year em{color:#002b36}body{text-align:center;font-size:16px}body > #entete{position:absolute;left:0;top:.5em;width:100%;min-width:50em;z-index:8000;padding-bottom:1em;margin-bottom:3em}#titre h2{width:80%;margin-left:auto;margin-right:auto;text-align:center;color:#ccccd0}#titre{text-align:center;width:100%}#titre h1,#titre h2{padding-left:1em;padding-right:1em}#bottom{clear:right;margin-right:0;padding:1.5em;line-height:1.5em;color:#224d58;margin-top:2em;text-align:center}#bottom a{color:#113c47}#bottom a:hover{color:#cb4b16}#sousliens{padding:1em 0;line-height:2em}#sousliens ul{list-style:none;margin-left:4em}ul.horizontal li{display:inline;font-size:.9em}ul.horizontal{margin-top:0;margin-bottom:0}#entete{padding-top:.1em;border-top:1px solid #ccccd0;border-bottom:1px solid #ccccd0}#liens{width:100%;padding:0;clear:both;margin-top:.5em}#liens ul{width:100%;clear:both;padding:0;margin:0}#liens ul li{display:inline-block;height:4em;margin-left:.2em;margin-right:.2em;width:23%}#liens ul li a,#liens ul li span{width:100%;display:block;line-height:4em}.clear{clear:both}#content{line-height:4em;margin-left:auto;margin-right:auto;margin-top:0;position:relative;clear:both;width:52em}.encadre,.black,.intro,.resume,.shadow{padding:2em;margin-top:2em;margin-bottom:2em}.encadre,.black,.shadow{color:#002b36;border:#ccccd0 solid 1px;border-radius:5px;box-shadow:0 0 2px #ccccd0 inset;background-color:#eeeef1}.encadre a,.black a,.shadow a{color:#667}.encadre a:hover,.black a:hover,.shadow a:hover{color:#cb4b16}.encadre a:hover strong,.encadre a:hover b,.encadre a:hover i,.encadre a:hover em,.encadre a:hover .nicer,.black a:hover strong,.black a:hover b,.black a:hover i,.black a:hover em,.black a:hover .nicer,.shadow a:hover strong,.shadow a:hover b,.shadow a:hover i,.shadow a:hover em,.shadow a:hover .nicer{color:#ffb17c}.encadre hr,.black hr,.shadow hr{color:#667;border-top:1px solid#667}.encadre strong,.encadre b,.encadre i,.encadre em,.black strong,.black b,.black i,.black em,.shadow strong,.shadow b,.shadow i,.shadow em{color:#002b36}.intro,.resume{font-size:.9em;font-style:italic;padding:.5em 1em;color:#556}.intro a:hover,.resume a:hover{color:#cb4b16}.intro i,.intro em,.resume i,.resume em{font-weight:400;font-style:normal;color:#002b36}.intro strong,.intro b,.resume strong,.resume b{font-weight:700;color:#002b36}#afterheader > h1{width:100%;padding-top:1.5em;text-align:left}#afterheader{padding-left:0;padding-right:0}#sousliens{margin-top:3em;margin-bottom:3em;font-size:1.2em;letter-spacing:1px;text-align:left;clear:both}.twilight{line-height:1.1em}.corps{font-size:1.25em;line-height:1.5em;text-align:justify;padding:3em 3em;margin:0;clear:both}.corps p,.corps ol,.corps ul,.corps blockquote,.corps pre,.corps code{margin-top:1.5em;margin-bottom:1.5em}.corps pre code{margin:0}.corps p,.corps ol,.corps ul,.corps blockquote{line-height:1.5em}.corps pre,.corps code{line-height:1em}.corps ul li ul,.corps ol li ul,.corps ul li ol,.corps ol li ol{margin-top:0;margin-bottom:0}.corps img{max-width:80%;border:1px solid #ccccd0;background-color:#fafafc;padding:.5em;box-shadow:0 10px 15px#ccc;border-radius:3px}.corps a:hover img{background-color:#dc3a05}figure{margin:3em 0}figure img{box-shadow:0 10px 15px#ccc inset}figure figcaption{text-align:center;margin:.5em 0}figure.left,figure.right{max-width:30%}img.clean{border:none;background-color:none;box-shadow:none}#address{clear:both}.definitionCell{width:5em;vertical-align:top;text-align:center;font-weight:700}.valueCell{text-align:right}.smallblock{float:left;width:50%;font-size:1em;font-weight:700}.largeblock{float:right;width:70%;font-size:1em}#blackpage,#nojsredirect{top:0;left:0;width:100%;min-height:100%;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;position:absolute;text-align:center}#blackpage{color:#002b36;background-color:#fafafc;font-family:Georgia,serif;font-style:italic;padding-top:8em;z-index:9000;cursor:wait}#blackpage .corps code,#blackpage .corps pre{font-family:monospace}#blackpage img{background:none;border:none;max-width:80%;margin:0 auto}#blackpage a{cursor:pointer}#blackpage .preh1{font-size:1.5em;font-weight:700;margin-bottom:1em}#blackpage .preh2{font-size:1.2em;font-style:italic;margin-bottom:1em}#blackpage .preintro{text-align:left;width:52em;margin:0 auto}#nojsredirect{z-index:9001}.nojsbutton{width:50%;padding:1em;border:solid 3px white;margin-left:auto;margin-right:auto;margin-top:2em;z-index:9002}.codefile{font-size:.8em;text-align:right;padding-right:1em;margin-right:.1;margin-bottom:-1em}.flush{clear:both}table.description{border-spacing:5px;border-collapse:separate;margin-right:auto;margin-left:auto}table.description tr td{padding-left:.5em;padding-right:.5em;padding-top:.5ex;padding-bottom:.5ex;vertical-align:middle;margin-right:5px}ul.long li{margin-bottom:1em}img{display:block;margin:1.2em auto;background:none;border:none}img.right{max-width:30%;margin-top:.6em;margin-left:2em}img.left{float:left;max-width:30%;margin-top:.6em;margin-right:2em}img.inside{display:inline;vertical-align:middle}pre{overflow-x:auto;overflow-y:hidden}.navigationprev,.navigationnext{padding:0;margin-left:.2em;margin-right:.2em;margin-bottom:0;margin-top:3em;width:45%}.navigation .navigationprev,.navigation .navigationnext{width:30%;margin-top:0}.navigation{height:4em;border-bottom:#ccccd0 solid 1px}.presarticleleft,.presarticleright{font-size:1em}.navigationprev{float:left;text-align:left}.navigationnext{float:right;text-align:right}.impact,.darkimpact{text-align:left;width:66%;padding-left:.25em;padding-right:.25em}table.impact{text-align:left}table.impact tr td{padding-left:.25em;padding-right:.25em}#liens{font-size:1.2em}#iemessage{font-size:1.2em;color:#ccc;margin:-10px;padding:1px 0;background:#333}#iemessage strong,#iemessage b,#iemessage i,#iemessage em{color:#ccc}#iemessage a,#iemessage a:visited{color:#eca}.tagname{display:inline;cursor:pointer;margin-left:.5em;margin-right:.5em}.list{margin-top:3em}#menuMessage{font-size:1.2em;line-height:1.5em;width:100%;text-align:center}#next_before_articles{clear:both;width:100%;font-size:1.2em;padding-top:1em;padding-bottom:1em}#previous_articles,#next_articles{color:#889;font-size:.8em;font-style:italic}#previous_articles{float:left;margin-left:1em;width:45%;text-align:left}.previous_article,.next_article{margin-top:1em}#next_articles{float:right;width:45%;margin-right:1em;text-align:right}#rss{font-size:1.2em;text-align:center;display:block;width:100%;float:right;padding:1em .1em}.corps .return a{color:#eeeef1;padding:.1em;line-height:1.5em;font-size:1.5em;height:1.5em;float:left;font-size:2em;margin-top:-0.5em;margin-left:-2em;width:1.5em}a.return{color:#eeeef1;padding:.1em;line-height:1.5em;font-size:1.5em;height:1.5em;font-size:2em;width:1.5em;display:block}a.return:hover{color:#889}.corps .return a:hover{color:#cb4b16}.footnotes{font-size:.8em}.footnotes ol{color:#839496;font-weight:700}.footnotes ol p{color:#002b36;font-weight:400;font-style:normal}.fontnotes ol{margin-left:0}.typeset img{display:inline;border:none;margin:0;padding:0}strong,b,i,em{color:#889}strong a,b a,i a,em a{color:#002b36}strong a:hover,b a:hover,i a:hover,em a:hover{color:#cb4b16}.corps p strong,.corps p b,.corps p i,.corps p em{color:#556}a:hover strong,a:hover b,a:hover i,a:hover em{color:#dc5c27}a:hover .nicer{color:#ffb17c}.nicer{color:#ccccd0;font-family:"Lucida Grande",Tahoma}.block{border:solid 1px #ccccd0;border-radius:2px;box-shadow:0 0 4px #f2f2f4 inset;background-color:#f8f8fa;width:26.5%;padding:1em;border-radius:2px;text-align:left;line-height:1em;margin-left:1%;margin-right:1%;font-size:.8em;height:9em}.block a{color:#002b36}.block a:hover{color:#cb4b16}.block h3{margin:0;font-size:1.3em}.block p{line-height:1.2em}.left{float:left}.right{float:right}.corps p a,.corps ul a{color:#556}.corps p a:hover,.corps ul a:hover{color:#cb4b16}ul.bloglist,.archive ul{list-style-type:none;margin:0}ul.bloglist li,.archive ul li{margin-bottom:1em}.button{cursor:pointer;text-align:center}#tagcloud{font-size:.8em;background:#f2f2f4;box-shadow:0 0 6px #ccccd0;border-radius:3px;line-height:2.5em;padding:2em;text-align:justify}.pala{font-family:Palatino}sup{vertical-align:top;font-size:.7em}.article .corps a:after{content:"†";vertical-align:super;line-height:0;font-size:.66em;color:#889}.article .corps .footnotes a:after,.article .corps sup a:after{content:""}.article .corps sup a{font-weight:700;padding:0 .3em;margin-left:2px;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}.article .corps sup a:hover{color:#cb4b16}ul#markdown-toc,.intro .toc ul{text-transform:uppercase;font-size:.8em;list-style:none;padding-left:1.5em}ul#markdown-toc a:after,.intro .toc ul a:after{content:""}ul#markdown-toc ul ul,.intro .toc ul ul ul{font-variant:normal;line-height:1em;font-size:1em;margin-bottom:1em}table{border:1px solid #ccccd0}table tr td{padding:2px .5em}table tr:nth-child(odd){background-color:#f2f2f4}table tr:nth-child(even){background-color:#fafafc}p pre code,ul li pre code,ol li pre code{background:none;border:none;padding:0}p code,ul li code,ol li code{background:#f0f0f2;border:solid 1px #ccccd0;padding:2px}ul.sameline{list-style:none}ul.sameline li{float:left;margin-left:.5em}.resumearticle{background-color:#f2f2f4;border-radius:7px;box-shadow:0 0 5px #c7c7b8 inset,0 0 5px white;margin:1em 0;padding:1em}a.cut{font-size:12px;text-align:right;display:block;width:100%;opacity:.5;border:1px solid #fafafc;border-radius:3px}a.cut:hover{opacity:1;background-color:#f2f2f4;border-color:#ccccd0;box-shadow:0 0 3px #ccccd0 inset}a.cut strong{font-weight:700}.codehighlight pre{border-left:4px solid #ccccd0}#social{text-align:left;opacity:.3}#social:hover{opacity:1}.popularblock{width:30.3333%;margin:0 1.5%;float:left}.popularblock figure{margin:0}.popularblock figure img{max-width:80%;max-height:6em}section.slide{border-color:#ccccd0;border:solid 1px;margin-bottom:1em;padding:.5em}.base03{color:#002b36}.base02{color:#073642}.base01{color:#586e75}.base00{color:#657b83}.base0{color:#839496}.base1{color:#93a1a1}.base2{color:#eee8d5}.base3{color:#fdf6e3}.yellow{color:#b58900}.orange{color:#cb4b16}.red{color:#dc322f}.magenta{color:#d33682}.violet{color:#6c71c4}.blue{color:#268bd2}.cyan{color:#2aa198}.green{color:#859900} \ No newline at end of file diff --git a/output/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html b/output/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html index be3e88bb5..f92ecf71d 100644 --- a/output/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html +++ b/output/Scratch/en/blog/Haskell-OpenGL-Mandelbrot/index.html @@ -2017,6 +2017,10 @@ O(n².log(n)) to O(n³).