iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Software Development

Functional Programming For Everyone系列 第 17

Day 17 - Applicative

Introduction

Type Signature

of :: Applicative f => a -> f a

Law

  • Identity: v.ap(A.of(x => x)) === v
  • homomorphism: A.of(x).ap(A.of(f)) === A.of(f(x))
  • intercharge: A.of(y).ap(u) === u.ap(A.of(f => f(y)))

Implement

Identity.of = x => Identity(x);
// Identity
Identity(1).ap(Identity.of(x => x)) === Identity(1);
// homomorphism
Identity.of(1).ap(Identity.of(add(1))) === Identity.of(add(1)(1))
// intercharge
Identity.of(1).ap(Identity.of(add(1))) === Identity(add(1)).ap(Identity(f => f(1)))

usage

想像一下在上一章 Apply 上提到的, 若一個 Monoid 是有 concat method 功用是將進行合併,並且有 empty 作為初始值,那 Applicative Functor 就是有 ap method 將 Container 進行合併,並有 of 作為該Container 初始的值。

例如我們現在有一個函式 h, 其 signature 為

h :: a -> f b -> f c

若要執行 h 函式,就需要先放入 af b,但很不巧的我們只有 b 此時 of 就非常有用,其將 b 包覆到其 Container。若現在有 of 這個 method 在 f 內,我們就可以透過 f.of(b) 轉換成我們所需的第二個參數 f b

再舉例來說,未來的章節裡我們一個概念 Sequence

const append = y => xs => xs.concat([y]);

const mySequence = (A, xs) => xs.reduce((acc, val) => lift2(append)(val)(acc), A.of([]))

mySequence(Identity, [Identity(1), Identity(2), Identity(3)]) // Identity([1, 2, 3])

其可以將 Container 內的值收集到同組資料結構,像是 Map, Array... 等,而這有什麼用呢? 未來我們會介紹到專門處理非同步的 Task Monad,而此概念就可以發揮極大的效果

sequence(Task, [Task(getUserList), Task(getCategroy)]) // Task([[...users, ...categroy]]) 

小結

到目前為止,我們還沒有介紹如何將 Effect 與 Effect 進行 compose,而下一章我們將會介紹到它 Chain

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 ?

Chain

感謝大家閱讀!

Reference

  1. Applicative

上一篇
Day 16 - Apply
下一篇
Day 18 - Chain
系列文
Functional Programming For Everyone30

尚未有邦友留言

立即登入留言