Slide 1

Slide 1 text

HOW TO BECOME A BETTER PROGRAMMER FROM REACT TO PURESCRIPT RAY SHIH

Slide 2

Slide 2 text

WHO AM I RAY SHIH • My name is Ray Shih • B.S., M.S. of NTU CSIE • Worked in WOOMOO • Worked in Mobiusbobs • Freelancer for now, next stop: FB in London • A Fullstack Software Engineer, including • iOS, Android, Web backend/Frontend • Learn Haskell/PureScript as a hobby :D

Slide 3

Slide 3 text

BEFORE WE START AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling ▸ View update ▸ Async operations and other side effects ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 4

Slide 4 text

WHAT IS “UI”?

Slide 5

Slide 5 text

https://jsbin.com/caxujex/1/edit?html,js,output

Slide 6

Slide 6 text

User Clicks Add 1

Slide 7

Slide 7 text

Click me!
0
$(() => { const display = $("#numDisplay") $("button").on('click', () => { display.text(parseInt(display.text()) + 1) }) })

Slide 8

Slide 8 text

OVERVIEW AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling ▸ View update ▸ Async operations and other side effects ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 9

Slide 9 text

$(() => { const display = $("#numDisplay") $("button").on('click', () => { display.text(parseInt(display.text()) + 1) }) }) Event handler registration Event name Event handler callback

Slide 10

Slide 10 text

$(() => { const display = $("#numDisplay") $("button").on('click', () => { display.text(parseInt(display.text()) + 1) }) }) Anonymous function!!!
 aka callback
 aka arrow function
 aka first class function

Slide 11

Slide 11 text

COMPARISON: JAVA 7 VS JAVASCRIPT final Button button = findViewById(R.id.button_id); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Code here executes on main thread // after user presses button } }); $("button").on('click', () => { display.text(parseInt(display.text()) + 1) }) No first class function
 So need a anonymous object First class function: Simple! from https://developer.android.com/reference/android/widget/Button.html

Slide 12

Slide 12 text

WE HAVE ANONYMOUS FUNCTION IN JAVA 8 BUT NOT FIRST CLASS Function add1 = x -> x + 1; Integer two = add1.apply(1); // yields 2 const add1 = x => x + 1 const two = add1(1) First class function: Simple! This is how to invoke a anonymous function in Java 8 https://dzone.com/articles/functional-programming-java-8

Slide 13

Slide 13 text

FIRST CLASS FUNCTION IS GOOD

Slide 14

Slide 14 text

BACK TO FIRST CLASS FUNCTION BUT NO CURRY const updateCounter = (f, user) => { const { loginCount } = user return { ...user, loginCount: f(loginCount) } } const add = (a, b) => a + b updateCounter(add(1), user) // nope you can't There are some library can do auto curry,
 but often make the type checker fails.

Slide 15

Slide 15 text

OVERVIEW AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling => First class function ▸ View update ▸ Async operations and other side effects ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 16

Slide 16 text

OVERVIEW AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling => First class function ▸ View update ▸ Async operations and other side effects ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 17

Slide 17 text

$(() => { const display = $("#numDisplay") $("button").on('click', () => { display.text(parseInt(display.text()) + 1) }) }) No structure. Let’s try MVC?

Slide 18

Slide 18 text

var num = 0 const display = $("#numDisplay") const render = () => display.text(num) $("button").on('click', () => { num += 1 render() }) Model View Controller? https://jsbin.com/caxujex/3/edit?html,js,output

Slide 19

Slide 19 text

VIEW UPDATE SO WHY REACT? ▸ Hard to synchronize model with view ▸ View binding! How? ▸ Re-render entire view! => React render function ▸ Slow? => React VirtualDOM!

Slide 20

Slide 20 text

// js const render = (model) => { // implementation return view } IDEALLY, REACT IS A FUNCTION FROM MODEL TO VIEW

Slide 21

Slide 21 text

HOW DOES REACT REALLY LOOK LIKE? class Counter extends React.Component { constructor() { super() this.state = { num: 0 } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState({ num: this.state.num + 1 }) } render() { return (
Click Me!
{this.state.num}
) } } ReactDOM.render( , document.getElementById("app") ) https://jsbin.com/leceser/1/edit?html,js,output View Event handler
 and
 Update state Model (state)

Slide 22

Slide 22 text

VIEW UPDATE REACT IS PERFORMANT! (OR NOT?) ▸ You need to implement `shouldComponentUpdate` properly ▸ or use `PureComponent` with ImmutableJS ▸ which implies we need ▸ Immutability ▸ Pure function

Slide 23

Slide 23 text

VIEW UPDATE REACT IS EASIER TO MAINTAIN! (OR NOT?) ▸ So we need redux from: https://victorliew.quora.com/A-summary-of-ReactJS-and-Flux

Slide 24

Slide 24 text

REDUX EXAMPLE const store = Redux.createStore((state = 0, action) => { switch (action.type) { case 'CLICK': return state + 1; default: return state } }) const Counter = ({ num, handleClick }) => (
Click Me!
{num}
) const handleClick = () => store.dispatch({ type: 'CLICK' }) const render = () => { ReactDOM.render( , document.getElementById("app") ) } store.subscribe(render) render()

Slide 25

Slide 25 text

REDUX EXAMPLE const store = Redux.createStore((state = 0, action) => { switch (action.type) { case 'CLICK': return state + 1; default: return state } }) const Counter = ({ num, handleClick }) => (
Click Me!
{num}
) const handleClick = () => store.dispatch({ type: 'CLICK' }) const render = () => { ReactDOM.render( , document.getElementById("app") ) } store.subscribe(render) render() State Action Redux helps developers to separate concern
 But also let developers worry about
 whether the types are matched Current solutions: FlowType, TypeScript Pure Function!

Slide 26

Slide 26 text

VIEW UPDATE CONFLICTS ▸ It’s hard to combine ImmutableJS with FlowType ▸ Ramda is kind of ok with FlowType but very fragile ▸ The problem is type system need to be strong and 100% enforced, otherwise you can’t trust it. ▸ Due to the same reason, FB is building ReasonML.
 Ref: https://youtu.be/tCVXp6gFD8o

Slide 27

Slide 27 text

OVERVIEW AGENDA ▸ What is “UI”? And how does React solve them? ▸ Event handling => First class function ▸ View update => Pure & Static type checker ▸ Async operations and other side effects ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 28

Slide 28 text

OVERVIEW AGENDA ▸ What is “UI”? And how does React solve them? ▸ Event handling => First class function ▸ View update => Pure & Static type checker ▸ Async operations and other side effects ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 29

Slide 29 text

ASYNC OPERATIONS VANILLA JS const queryA = (cb) => { ... } const queryB = (a, cb) => { ... } const queryC = (b, cb) => { ... } const dispatch = (a, b, c) => { ... } How to combine those functions?

Slide 30

Slide 30 text

ASYNC OPERATIONS VANILLA JS const queryA = (cb) => { ... } const queryB = (a, cb) => { ... } const queryC = (b, cb) => { ... } const dispatch = (a, b, c) => { ... } const fetch = (cb) => { queryA(a => { queryB(a, b => { queryC(b, c => { dispatch(a, b, c) }) }) }) } Callback Hell!!! How to combine those functions?

Slide 31

Slide 31 text

ASYNC OPERATIONS PROMISE CAN SOLVE IT (OR CAN’T IT?) const fetch = () => queryA().then(a => ( queryB(a).then(b => ( queryC(b).then(c => ( [a, b ,c] )) )) )) .then(([a, b, c]) => { dispatch(a, b, c) }) Callback Hell!!! How to combine those promises?

Slide 32

Slide 32 text

ASYNC OPERATIONS PROMISE CAN SOLVE IT (OR CAN’T IT?) — SECOND TRY Seriously? const fetch = () => queryA() .then(a => queryB(a).then(b => [a, b])) .then(([a, b]) => queryB(b).then(c => [a, b, c])) .then(([a, b, c]) => dispatch(a, b, c)) How to combine those promises?

Slide 33

Slide 33 text

ASYNC OPERATIONS RX BASED (REDUX OBSERVABLE) const fetch = () => queryA().flatMap(a => ( queryB(a).flatMap(b => ( queryC(b).flatMap(c => ( [a, b, c] )) )) )) .subscribe(([a, b, c]) => { dispatch(a, b, c) }) const fetch = () => queryA().then(a => ( queryB(a).then(b => ( queryC(b).then(c => ( [a, b ,c] )) )) )) .then(([a, b, c]) => { dispatch(a, b, c) }) Really no big difference Similarity between Rx and Promise
 There must be something How to combine those observables?

Slide 34

Slide 34 text

ASYNC OPERATIONS REDUX SAGA BASED function* fetch() { const a = yield call(queryA) const b = yield call(queryB, a) const c = yield call(queryC, b) yield put({ type: 'UPDATE', a, b, c}) } This is what we want right?
 There is also async/await
 but we can actually do more How to combine those ??????

Slide 35

Slide 35 text

WE NEED A SYNTAX TO COMBINE THOSE SPECIAL THINGS

Slide 36

Slide 36 text

OVERVIEW AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling => First class function ▸ View update => Pure & Static type checker ▸ Async operations and other side effects
 => ”Special” function composition ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 37

Slide 37 text

THE WAY TO FUNCTIONAL PROGRAMMING THINGS WE FOUND USEFUL ▸ First class function ▸ Purity/Immutable ▸ Static type analysis ▸ “Special” function composition

Slide 38

Slide 38 text

THE WAY TO FUNCTIONAL PROGRAMMING BUT CURRENT JS ISN’T DOING WELL ▸ First class function => No built in curry ▸ Purity/Immutable => No way to guarantee ▸ Static type analysis => None of them are perfect ▸ “Special” function composition => generator kind of does this job, but we can do it better

Slide 39

Slide 39 text

THE WAY TO FUNCTIONAL PROGRAMMING PURESCRIPT ▸ First class function => Checked ▸ Purity/Immutable => Checked ▸ Static type analysis => Checked ▸ “Special” function composition => Checked

Slide 40

Slide 40 text

OVERVIEW AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling => First class function ▸ View update => Pure & Static type checker ▸ Async operations and other side effects
 => ”Special” function composition ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 41

Slide 41 text

PURESCRIPT IS COOL WHAT IS PURESCRIPT ▸ A strongly-typed functional programming language that compiles to JavaScript!

Slide 42

Slide 42 text

PURESCRIPT IS COOL WHAT IS PURESCRIPT ▸ A strongly-typed ▸ functional programming language, that ▸ compiles to JavaScript! ▸ Think about CoffeeScript, TypeScript, Babel…etc ▸ Yup PureScript is one of them

Slide 43

Slide 43 text

OVERVIEW AGENDA ▸ What is “UI”? And how React solve them? ▸ Event handling => First class function ▸ View update => Pure & Static type checker ▸ Async operations and other side effects
 => ”Special” function composition ▸ The problems we still have after React. ▸ What does PureScript help? ▸ Some examples of PureScript

Slide 44

Slide 44 text

PURESCRIPT EXAMPLES CURRY? OR “I DON’T CARE”? add :: Int -> Int -> Int add a b = a + b arr = [1, 2, 3] map (add 1) arr -- [2, 3, 4] In PureScript In JS const add = (a: number) => (b: number): number => a + b const arr = [1, 2, 3] arr.map(add(1))

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

PURESCRIPT EXAMPLES PURITY/IMMUTABLE ▸ There is no variable => you can’t change anything ▸ Immutable (of course) ▸ Pure function (of course) ▸ The interesting part: ▸ Pure function doesn’t limit you to do anything

Slide 47

Slide 47 text

PURESCRIPT EXAMPLES STATIC TYPE ANALYSIS ▸ PureScript is a compiled language with ▸ Hindley-Milner type system ▸ Same as Haskell ▸ “if a Haskell program compiles, it probably works"

Slide 48

Slide 48 text

PURESCRIPT EXAMPLES ASYNC OPERATIONS AND OTHER SIDE EFFECTS 1 — ASYNC QUERY In PureScript In JS function* fetch() { const a = yield call(queryA) const b = yield call(queryB, a) const c = yield call(queryC, b) yield put({ type: 'UPDATE', a, b, c}) } fetch = do a <- queryA b <- queryB a c <- queryC b dispatch a b c

Slide 49

Slide 49 text

PURESCRIPT EXAMPLES ASYNC OPERATIONS AND OTHER SIDE EFFECTS 2 — MAYBE In PureScript In JS const getGreatGrandParent = person => { const parent = getParent(person) if (parent == null) return null const grandParent = getParent(parent) if (grandParent == null) return null return getParent(grandParent) } getGreatGrandParent person = do parent <- getParent person grandParent <- getParent parent getParent grandParent

Slide 50

Slide 50 text

PURESCRIPT EXAMPLES ASYNC OPERATIONS AND OTHER SIDE EFFECTS 3 — LIST In PureScript In JS const getGreatGrandChildren = person => getChildren(person) .map(getChildren).flatten() .map(getChildren).flatten() getGreatGrandChildren person = do child <- getChildren person grandChild <- getChildren child getChildren grandChild

Slide 51

Slide 51 text

AND MANY MORE

Slide 52

Slide 52 text

MORE JAVASCRIPT INTEROPERATION ▸ It actually compiles to JavaScript without runtime ▸ Can invoke JS function (after annotate the type) ▸ So you can use PureScript partially

Slide 53

Slide 53 text

LET’S LEARN HOW TO START? ▸ Books! ▸ PureScript by Example ▸ Learn you a Haskell ▸ Find a mentor ▸ Join a study group ▸ https://try.purescript.org

Slide 54

Slide 54 text

JUST TRY IT SERIOUSLY, HOW TO START? ▸ npm install -g purescript pulp bower ▸ mkdir purescript-hello ▸ cd purescript-hello ▸ pulp init ▸ pulp run

Slide 55

Slide 55 text

JUST TRY IT SOME LIBRARIES ▸ Pux — almost like redux ▸ e.g. https://github.com/rayshih/pux-todomvc ▸ Lens — cool library to operate on nested data and more ▸ Async — you need this to perform async tasks ▸ Simple JSON — the easiest way to parse JSON safely

Slide 56

Slide 56 text

MY SECRET HOW TO LEARN OOP WELL The secret is: learn functional programming https://www.slideshare.net/ScottWlaschin/fp-patterns-buildstufflt

Slide 57

Slide 57 text

THANKS AND Q&A