## Bartosz Szewczyk

Frontend developer @codete

# “Monad is a monoid in the category of endofunctors”

## Bartosz Milewski

Category Theory for programmers

## Fantasy-land

Specification for interoperability of common algebraic structures in JavaScript

https://github.com/fantasyland/fantasy-land

"A value that implements the Monad specification must also implement the Applicative and Chain specifications."

# No null type in Haskell

### "I call it my billion-dollar mistake" - Tony Hoare about null reference

``type Maybe<A> = A | null``

# Typescript

``````function map<A, B>
(m: Maybe<A>, fn: (a: A) => B): Maybe<B> {
if (m === null) {
return null
} else {
return fn(m)
}
}``````

# Typescript

``data Maybe a = Just a | Nothing``

``````map :: Maybe a -> (a -> b) -> Maybe b
map m fn =
case m of
Nothing -> Nothing
Just a -> Just (fn a)``````

## Composition problem

``````map(
map(
bind(
unit(a),
x => foo(x)
), y => bar(y)
), z => baz(z)
)``````
``````Maybe.unit(a)
.bind(x => foo(x))
.map(y => bar(y))
.map(z => baz(z))``````

``````class Maybe<T> {

static unit<T>(t: T | null): Maybe<T>

map<U>(fn: (t: T) => U) : Maybe<U>

bind<U>(fn: (t: T) => Maybe<U>): Maybe<U>

caseOf<U>(cases: MaybeCases<T, U>): Maybe<U>

}

function join<T>(m: Maybe<Maybe<T>>): Maybe<T>``````

``````filter(fn: (t: T) => boolean): Maybe<T> {
return this.caseOf({
nothing: () => Maybe.nothing(),
just: (t: T) => fn(t) ? this : Maybe.nothing()
})
}``````

## Imperative way

``````function getCountry(student) {
const school = student.school()
if (scholl !== null) {
}
}
return 'Country does not exist'
}``````

``````function getCountry(student) {
return maybe(student)
.map(student => student.school())
.caseOf({
nothing: () => 'Country does not exists',
just: country => country
})
}``````

``````// Left identity:
unit(a).bind(f) === f(a)

// Right identity:
m.bind(unit) === m

// Associativity:
m.bind(f).bind(g) === m.bind(x => f(x).bind(g))``````
`Could also be unit, join, map`

### "There is no smart quote that disqualifies usage of exceptions" - Bartosz Szewczyk

``````function twoDivideBy(n: number) : number {
return 2 / n
}

[4, 3, 2, 1, 0].map(twoDivideBy)``````

# Typescript

``````function twoDivideBy(n: number) : number {
if (n === 0)
throw new Error('Cannot divide by zero')
return 2 / n
}

[4, 3, 2, 1, 0].map(twoDivideBy)``````

# Exceptions?

``````type Either<L, R> = Left<L> | Right<R>

function twoDivideBy(n: number)
: Either<string, number>
{
if (n === 0) {
return Either.left(
"Cannot divide by zero")
} else {
return Either.right(2 / n)
}
}``````

``````const validName = validateName(name)
if (!validName) {
return dispatchErr('Not valid name')
}

if (!validPasswd) {
}

# Typescript

``````Either.right({name, passwd})
.bind(args => validateName(args.name)
? Either.right(args)
: Either.left('Not valid name')
)
.bind(args => validatePasswd(args.passwd)
? Either.right(args)
)
.do({
left: msg => dispatchErr(msg),
right: args => doRequest(args),
})``````

# Typescript

``````Either.right({name, passwd})
.bind(args => validateNameM(args.name))
.bind(args => validatePasswdM(args.passwd))
.do({
left: msg => dispatchErr(msg),
right: args => doRequest(args),
})``````

# Typescript

``````EitherPromise.right(fetch(url1))
.caseOf({
resolve: (resp) => right(resp.json())
reject: (err) => left(err)
})``````

# Promises

``````// Left identity (f must return Promise):
Promise.resolve(a).then(f) === f(a)

// Right identity:
p.then(Promise.resolve) === p

// Associativity (f must return Promise):
p.then(f).then(g) === p.then(x => f(x).then(g))``````

``````// Left identity:
Observable.of(a).switchMap(f) === f(a)

// Right identity:
stream.switchMap(Observable.of) === stream

// Associativity:
stream.switchMap(f).switchMap(g) ===
stream.switchMap(x => f(x).switchMap(g))``````

"The last thing you wanted any programmer to do is mess with internal state(...)" - Alan Kay

## Recursion problem

``````type Con = {con: number}
type Div = {div: [Tree, Tree]}
type Tree = Div | Con

eval({
div: [
{
div: [
{con: 1972},
{con: 2}
]
},
{con: 23}
]
})``````
``(1972 / 2) / 23``

## Counting recursions

``````function eval(tree: Tree, n: number) {
if (isCon(tree)) {
return [tree.con, n]
}
const [t1, n1] = eval(tree.div[0], n)
const [t2, n2] = eval(tree.div[1], n1)
return [t1 / t2, n2 + 1]
}``````

``````type M<A> = State => [A, State]
type State = number``````

``````function eval(tree: Tree): M<number> {
if (isCon(tree)) {
return (s: State) => [tree.con, s]
}
return (s: State) => {
const [t1, s1] = eval(tree.div[0])(s)
const [t2, s2] = eval(tree.div[1])(s1)
return [t1 / t2, s2 + 1]
}
}``````

``````class StateM<T> {

constructor(f: (s: State) => [T, State])

static unit<T>(t: T): StateM<T>

bind<U>(f: (t0: T) => StateM<U>): StateM<U>
}``````

## Small addition for the sake example

``````function tick(): StateM<undefined> {
return new StateM<undefined>((s: State) => {
return [undefined, s + 1]
})
}``````

``````function eval(tree: Tree): StateM<number> {
if (isCon(tree)) {
return StateM.unit(tree.con)
}
return eval(tree.div[0]).bind(t1 =>
eval(tree.div[1]).bind(t2 =>
tick().bind(() => StateM.unit(t1 / t2))
)
)
}``````

Take your State Monad and treat RealWorld as if it were State

## IO as basic block

``````type IO a = RealWorld -> (a, RealWorld)

main :: IO ()
main :: RealWorld -> ((), RealWorld)

getLine :: IO String
putStrLn :: String -> IO ()``````

``````main :: IO ()
main = putStrLn "What is your name?" >>= \() ->
putStrLn ("Hello, " ++ getLine)``````

Couldn’t match expected type String with actual type IO String
In the second argument of (++), namely getLine

## Will work

``````main :: IO ()
main = putStrLn "What is your name?" >>= \() ->
getLine >>= \n ->
putStrLn ("Hello, " ++ n)``````

## "JS" kinda way

``````const main = () =>
getLine().bind(n =>
putStrLn("Hello, " + n)
)``````

Close enough

## Basic cycle example

``````import { run } from '@cycle/run'

run(function main(sources) {
return {
DOM: sources.DOM.select('.counter')
.events('click').map(e => e)
.fold((agg, i) => agg + 1, 0)
.map(clicks => (
<div>
<div>Clicks: \${clicks}</div>,
<button className="counter">Click me!</button>
</div>
))
}
}, {
DOM: makeDOMDriver('#app')
})``````

## Andre Staltz:

What if the user was a function?

# That's all Folks

## Thank you for listening

github: sztobar

By Bartosz Szewczyk