SlideShare a Scribd company logo
Everything is
composable
Hello!I am Victor Igor
You can find me at @victorvoid
1.
Programming paradigms
A “new” perspective on modeling the flow of your software.
“
In practice, each paradigm comes with its
own way of thinking and there are
problems for which it is the best approach.
Programming paradigms
◍ Functional programming
◍ Object-oriented programming
◍ Logic programming
◍ Symbolic programming
Composability
The essence of software development is composition.
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
Composability
const doin_Thangs = str =>
_.chain(str)
.words()
.groupBy(s => s.length)
.orderBy(x => x.length)
.take(2)
.flatten()
.value()
Composability
const reactiveUpInHere = el =>
fromEvent(el, 'keyup')
.map(e => e.target.value)
.filter(text => text.length > 2)
.throttle(500)
.distinctUntilChanged()
Composability
(->> (range 1000000000000000000)
(filter even?)
(map inc)
(take 5)
(partition 2 1))
;;=> ((1 3) (3 5) (5 7) (7 9))
Composability
player
.unitWithinRange(2)
.where(UnitIs.Enemy)
.where(UnitIs.Tank)
.DoDamage(5)
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
‘Victor and Igor’
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
‘victor and igor’
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
[‘victor’,‘and’,‘igor’]
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
[‘victor’,‘and’,‘igor’]
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
[‘igor’,‘and’,‘victor’]
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
[‘igor’,‘victor’]
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
‘igorvictor’
Composability
const doThing = str => {
const lower = str.toLowerCase()
const words = lower.split(' ')
words.reverse()
for(let i in words) {
words[i] = words[i].trim()
}
let keepers = []
for(let i in words) {
if(words[i].length > 3) {
keepers.push(words[i])
}
}
return keepers.join('')
}
Composability
const doThing = str => {
const lower = str.toLowerCase()
const words = lower.split(' ')
words.reverse()
for(let i in words) {
words[i] = words[i].trim()
}
let keepers = []
for(let i in words) {
if(words[i].length > 3) {
keepers.push(words[i])
}
}
return keepers.join('')
}
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
Composability
Composability
“The major contributor to this complexity
in many systems is the handling of state
and the burden that this adds when trying
to analyse and reason about the system.”
Ben Moseley & Peter Marks
Out of the Pit 2006
Control flow
Composability
Composability
Code volume
Composability
Composability
Composability
Composability
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
Everything is composable
Everything is composable
Programming !== Math
Programming !== Math
Programming !== Math
try {
return f(x)
} catch(e) {
console.error(e)
}
Programming !== Math
if {
return f()
} else(e) {
return y
}
Programming !== Math
let stuff = [1, 2, 3]
stuff = [1, 2]
Programming !== Math
let stuff.splice(0, 2)
stuff.pop()
Programming !== Math
for(let thing in things) {
if(thing.amount > 100) keepers.push(thing.name)
}
for (i = 0; i < cars.length; i++) {
text += cars[i] + "<br>";
}
while (i < 10) {
text += "The number is " + i;
i++;
}
Assignment
Callbacks
Loops
Side Effects
Branching
Errors
Programming !== Math
Programming !== Math
Programming != Math
Programming !== Math
f.g
Programming !== Math
f.g = x => f(g(x))
Programming !== Math
str.toUpperCase().trim()
Programming !== Math
trim(toUpperCase(str))
Category theory
Category Theory
What’s category theory?
What’s category theory?
Category Theory
Categories represent abstraction of other mathematical concepts.
The paradigm shift provoked by Einstein's
theory of relativity has brought the
realization that there is no single
perspective to see the world.
Category
Category Theory
objects
Category
Category Theory
objects
Arrows or morphisms
Category
Category Theory
objects
Arrows or morphisms
Domain
dom(f) f
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
dom(f) f
cod(f)
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
dom(f)
g
cod(f)
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
f
Composition
h
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
f
Composition
h
h . f
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
Composition
Identity
World Wide Web
Category Theory
World Wide Web
Category Theory
objects = webpages
Arrows = hyperlinks
World Wide Web
Category Theory
objects = webpages
Arrows = hyperlinks
Composition = Links don’t compose
Identity
World Wide Web
Category Theory
objects = nodes
Arrows = edges
Composition = Edges don’t compose
Identity
Graphs
Category Theory
objects = sets (or types)
Arrows = functions
Composition = function composition
Identity = identity function
Programming
Functors
Category Theory
Category Theory
Functors map between categories
Functors
Category Theory
A B
Category Category
Functor
F
Category Theory
Composition Law
F(g ∘ f) = F(g) ∘ F(f)
Identity Law
F(idA) = idF(A)
Functors laws
Category Theory
“Hey, I know what can be mapped
over. An array can be mapped
over — you can map a function over an
array!”
Category Theory
Identity
const f = [1,2,3]
f.map(x => x) //[1,2,3]
Category Theory
Composition
[1,2,3].map(x => f(g(x)))
=
[1,2,3].map(g).map(f)
Composability
const nextCharForNumberString = str => {
const trimmed = str.trim()
const number = parseInt(trimmed)
const nextNumber = number + 1
return String.fromCharCode(nextNumber)
}
nextCharForNumberString(' 70 ')
//'G'
Composability
const nextCharForNumberString = str =>
return [str.trim()]
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.map(n => String.fromCharCode(n))
nextCharForNumberString(' 70')
//['G']
Category Theory
Build your own Functor
Composability
const Box = x => ({
map: f => Box(f(x))
})
const Box = x => ({
map: f => Box(f(x))
})
const nextCharForNumberString = str =>
return Box(str.trim())
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.map(n => String.fromCharCode(n))
nextCharForNumberString(' 70') //Box('G')
const Box = x => ({
map: f => Box(f(x)),
fold: f => f(x)
})
const nextCharForNumberString = str =>
return Box(str.trim())
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.fold(n => String.fromCharCode(n))
nextCharForNumberString(' 70') //'G'
Assignment
Callbacks
Loops
Side Effects
Branching
Errors
Loops
filter
map
reduce
Assignment
Callbacks
Loops
Side Effects
Branching
Errors
Callbacks
Side effects
Promise(5).then(five => five + 2)
//Promise(7)
Promise(5).then(five => Promise(five + 2))
//Promise(7)
Promise(5).map(five => five + 2))
//Promise(7)
const doThing = () =>
fs.readFile('file.json', 'utf-8', (err, data) => {
if(err) throw err
const newdata = data.replace(/8/g, '6')
fs.writeFile('file2.json', newdata, (err, _) => {
if(err) throw err
console.log('success!')
}
}
const readFile = futurize(fs.readFile)
const writeFile = futurize(fs.writefile)
const doThing = () =>
readFile('file.json')
.map(data => data.replace('/8/g', '6')
.chain(replaced =>
writeFile('file2.json', replaced))
const readFile = futurize(fs.readFile)
const writeFile = futurize(fs.writefile)
const doThing = () =>
readFile('file.json')
.map(data => data.replace('/8/g', '6')
.chain(replaced =>
writeFile('file2.json', replaced))
doThing().fork(e => console.log(e),
r => console.log('success'))
const lib = username =>
getTweets(username)
.map(tweets => truncateTo130(tweets))
.chain(tweets => writeFile('tweets.json', tweets))
lib('@victorvoid')
.chain(f => saveToS3(f))
.fork(e => console.error(e),
r => console.log(r))
Assignment
Callbacks
Loops
Side Effects
Branching
Errors
Errors
Branching
Either
data Either a b = Left a | Right b
Left('no loaded').fold(() => 'uow, error!',
s => s.toUpperCase())
//'uow, error!'
Right('loaded').fold(() => 'uow, error!',
s => s.toUpperCase())
//'LOADED'
LeftOrRight('no loaded')
.fold(() => 'uow, error!',
s => s.toUpperCase())
Right(2)
.map(x => x + 4)
.map(x => x / 2)
.fold(() => 'uow, error!',
r => r + 1)
//4
Left('ignored')
.map(x => x + 4)
.map(x => x / 2)
.fold(() => 'uow, error!',
r => r + 1)
//'uow, error!'
const getConfig = () => {
try {
return fs.readFileSync('config.json')
} catch (e) {
return null
}
}
const getPort = () => {
const str = getConfig()
if(str) {
const parsed = JSON.parse(str)
return parsed.port
} else (e) {
return 3000
}
}
const getConfig = () =>
Either.try(fs.readFileSync)('config.json')
const getPort = () =>
getConfig()
.map(JSON.parse)
.fold(e => 3000, c => c.port)
const getThing = user => {
const address = user.address
if(address){
const zip = address.match(/(d{5})$/i)
if(zip){
const city = cityByZip(zip)
if(city){
return city
} else {
return 'cant find city'
}
}
}
return 'cant find city'
}
const getThing = user =>
fromNullable(user.address)
.chain(a => fromNullable(a.match(/(d{5})$/i)))
.chain(zip => fromNullable(cityByZip(zip)))
.fold(() => 'cant find city', city => city)
Assignment
Callbacks
Loops
Side Effects
Branching
Errors
Everything is composable
React example
Component :: a -> JSX
a JSX bf g
a JSX bf g
a JSX
fb
g
const Comp = g => ({
fold: g,
contramap: f =>
Comp(x => g(f(x)))
})
const Comp = g => ({
fold: g,
contramap: f =>
Comp(x => g(f))
})
const heading = str =>
<h1>You are viewing {str}</h1>
const Title = Comp(heading).contramap(s => s.pageName)
const Comp = g => ({
fold: g,
contramap: f =>
Comp(x => g(f))
})
const heading = str =>
<h1>You are viewing {str}</h1>
const Title = Comp(heading).contramap(s => s.pageName)
Title.fold({ pageName: 'Home',
currUser: {id: '123', name: 'Victor'}})
//<h1>You are viewing Home</h1>
Learn a new language
Fantasy Land Specification
Everything is composable
References
- Mostly-adequate-guide
- Professor-frisby-introduces-composable-functional-javascript
- Ramda-fantasy
- Functors, Applicatives, And Monads In Pictures
- Bartosz Milewski - Category Theory for programmers
Thanks!Any questions?
You can find me at @victorvoid & victorvoid.me

More Related Content

Everything is composable