DAY 18
0
Software Development

## Day 18 - Chain

yo, what's up 又看到了這張熟悉的表了，想必大家都已經知道這章要來介紹什麼了，

## Review

f g composition
pure pure compose(f, g)
effects pure(unary) f.map(g)
effects pure(n-ary) f1.map(g).ap(f2)
effects effects ?

pure & pure

Function Composition 這章，我們已經提到如何用 `compose` 將兩(多)個純函式進行 compose

`compose`

``````const compose = (...fns) =>
fns.reduce(
(acc, fn) => (...args) => acc(fn(...args)),
x => x
)
``````

``````const f = str => str.toUpperCase();
const g = str => str.concat('!');

compose(g, f)('fp') // In math, we called g o f

// 'FP!'
``````

pure (un-ary) & effect

`map`

``````const Identity = val => ({
val,
map: f => Identity(f(val)),
inspect: () => `Identity(\${val})`
})
``````

``````Identity('fp').map(f).map(g).val // 'FP!'
``````

pure (n-ary) & effects

`ap`

``````const Identity = val => ({
val,
map: f => Identity(f(val)),
ap: function (o) {
return this.map(o.val);
},
inspect: () => `Identity(\${val})`
})

Identity.of = x => Identity(x)
``````

helper function `lift2`，若 `g` 的參數長度為 2

``````const lift2 = g => f1 => f2 => f2.ap(f1.map(g));
``````

`g` 一定要是 curried 函式

``````const concat = R.curry((x, y) => x.concat(y))

lift2(concat)(Identity.of('FP'))(Identity.of('!')).val // 'FP!'
``````

effect & effect

``````f :: a -> f a
g :: b -> f b
``````

``````// toUpper :: a -> Identity a
const toUpper = str => Identity.of(str.toUpperCase())
const exclaim = str => Identity.of(str.concat('!'))
``````

``````const result = Identity.of("fp")
.map(str => toUpper(str)) // Identity(Identity('FP'))

``````

``````result
.map(wrappedStr =>
wrappedStr.map(upperStr => exclaim(upperStr)) // Identity(Identity(Identity('FP!')))
)
``````

``````result.val.val.val
``````

## Introduction

`join`

``````const Identity = val => ({
val,
map: f => Identity(f(val)),
ap: function (o) {
return this.map(o.val);
},
join: () => val,
inspect: () => `Identity(\${val})`
})

Identity.of = x => Identity(x)
``````

`join` 做的事情非常簡單，就是打平結構

``````Identity.of("fp")
.map(toUpper)
.join()
.map(exclaim)
.join()
.val // 'FP!'
``````

Type Signature

``````chain :: Chain m => m a ~> (a -> m b) -> m b
``````

Law

• associativity: `m.chain(f).chain(g) === m.chain(x => f(x).chain(g))`

Implement

``````const Identity = val => ({
val,
map: f => Identity(f(val)),
ap: function (o) {
return this.map(o.val);
},
join: () => val,
chain: function (f) {
return this.map(f).join()
},
inspect: () => `Identity(\${val})`
})

Identity.of = x => Identity(x)
``````

``````Identity.of("fp")
.chain(toUpper)
.chain(exclaim)
.val // 'FP!'

// same as

Identity.of("fp").chain(x => toUpper(x).chain(exclaim)).val // 'FP!'
``````

isn't that neat!?

## 小結

f g composition
pure pure compose(f, g)
effects pure(unary) f.map(g)
effects pure(n-ary) f1.map(g).ap(f2)
effects effects m.chain(f).chain(g)