2. Haskell
● A standardized, general-purpose purely functional programming language,
with non-strict semantics and strong static typing.
● It is named after logician Haskell Curry.
● Elegant! Expressive! Fast! But, ...
I’m here !
3. Category Theory
Category
- A collection of objects
- A collection of morphism from one to another object
- Composition, a binary operation defined on compatible pairs of morphisms
- Require Associativity and Identity
Functor
A type of mapping between categories
class Functor f where
fmap :: (a -> b) -> f a -> f b
4. Functor in Haskell
Any type that takes one concrete type to produce a concrete type
- Maybe
- Tree
- Either
instance Functor Maybe where
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
instance Functor Tree where
fmap f EmptyTree = EmptyTree
fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right)
instance Functor Either a where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
‘Either a’, not ‘Either’. Why???
(b -> c) -> Either a b -> Either a c
(b -> c) -> (Either a) b -> (Either a) c
(b -> c) -> f b -> f c
5. How about function?
chr :: Int -> Char ord :: Char -> Int
Change to prefix form from infix form
chr :: (-> Int) Char ord :: (-> Char) Int
Function is a first-class citizen, not special.
(b -> c) -> (a -> b) -> ( a -> c)
(b -> c) -> (-> a) b -> (-> a) c
(b -> c) -> f b -> f c
instance Functor ((->) r) where
fmap = (.)
instance Functor IO where
fmap f action = do
result <- action
return (f result)
6. Functor and Currying
Currying is the process of transforming a function that takes multiple arguments
into a function that takes just a single argument and returns another function if any
arguments are still needed.
add :: Int -> Int -> Int add :: Int -> (Int -> Int)
add a b = a + b add a = b -> a + b
Functor should take one concrete type.
In Haskell, all function take one concrete type because of currying!
8. Lift?
● Takes a function and a functor values and then maps that function over the
functor value
fmap :: (a -> b) -> f a -> f b
● Takes a function and lifts that function so it operates on functor values
fmap :: (a -> b) -> (f a -> f b)
9. Applicative Functor
A pattern that popped up time and again in our daily work, effectual programming
in Haskell.[1]
● More instance and sufficient for many uses like context-free parsing
● instances can perform analysis of computations before they are executed,
and thus produce shared optimizations.
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
With Applicative type class, we can chain the use of the <*> function, thus
enabling us to seamlessly operate on several applicative values instead of just
one. [1] Functional pearl - Applicative programming with effects
10. Applicative Functors (1)
Maybe
instance Applicative May be where
pure = just
Nothing <*> _ = Nothing
(Just f) <*> x = fmap f x
List
instance Applicative [] where
pure x = [x]
fs <*> xs = [f x | f <- fs, x <- xs]
11. Applicative Style
pure (+) <*> Just 3 <*> Just 5 (pure (+) <*> Just 3) <*> Just 5
Isn’t this awesome?
Applicative functors and the applicative style of pure f <*> x <*> y <*> … allow us to
take a function that expects parameters that aren’t applicative values and use that
function to operate on several applicative values.
(<$>) :: (Functor f) => (a -> b) -> f a -> f b
f <$> x = pure f <*> x -- (1)
f <$> x = fmap f x -- (2) (1)is same with (2).
12. Applicative Functors (2)
IO
instance Applicative IO be where
pure = return
a <*> b = do f <- a
x <- b
return (f x)
Function
instance Applicative ((->) r) where
pure x = (_ -> x)
f <*> g = x -> f x (g x)
Example
(pure 3) “blah” == 3
(+) <$> (+3) <*> (*100) $ 5 == 508
(x y z -> [x,y,z]) <$> (+3) <*> (*2) <*>
(/2) $ 5 == [8.0,10.0,2.5]
13. Applicative Laws
Law 1
pure id <*> v = v
Law 2
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
Law 3
pure f <*> pure x = pure (f x)
Law 4
u <*> pure y = pure ($ y) <*> u
14. Monoid
In category theory, a monoid (or monoid object) (M, μ, η) in a monoidal category
(C, ⊗, I) is an object M together with two morphisms. It has a associativity binary
operator and identity element.
- μ: M ⊗ M → M called multiplication,
- η: I → M called unit,
class Monoid m where -- only concrete types can be made instances of Monoid
mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
mconcat = foldr mappend mempty
15. Monad
Monads are a natural extension of applicative functors.
If we have a value with a context, ‘m a’, how do we apply to it a function that takes
a ‘normal a’ and returns a ‘value with a context’?
Many common programming concepts can be described in terms of a monad
structure, including side effects such as input/output, variable assignment,
exception handling, parsing, nondeterminism, concurrency, and continuations.
Simply, Monads are programmable semicolons in the Haskell.
16. The Monad Type Class
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
x >> y = x >>= _ -> y
17. Example of Monad
/* Java */
String s = System.console().
readLine();
int n = Integer.parseInt(s);
n = n + 3
System.out.printf(“result:”);
System.out.printf(“%d”, n);
do Notation (Syntatic sugar!)
do s <- getLine
let n = read s :: Int
let n2 = n + 3
putStr “result: “
putStrLn $ show n2
getLine
>>= s -> let n = read s :: Int
n2 = n + 3
in putStr “result: “
>>= _ -> putStrLn $ show n2
18. Conclusion
Don’t concentrate on category theory itself.
Long time ago, old functional programmers found some patterns in their codes.
They want to generalize the found patterns and want to get an elegant abstraction.
But good abstraction is not a easy work. Some of them are also great
mathematician. They borrowed the concepts from mathematics like category
theory.
Don’t reinvent the wheel. Just use the wheel.
Of course, if you know why and how they made wheel, it’s very helpful to you.