Arrow function generic types

楔子 Arrow Function 很常使用,但它的 Generic Type 有點不太好記,列舉一下幾種 Generic Arrow Functions 正常的函數 Generice Type 的格式 function firstOrNull<T>(arr: T[]): T | null { return arr.length === 0 ? null : arr[0]; } General const firstOrNull = <T>( arr: T[] ): T | null => arr.length === 0 ? null : arr[0]; Extends trick const firstOrNull = <T extends unknown>( arr: T[] ): T | null => arr.length === 0 ? null : arr[0]; Comma trick const firstOrNull = <T,>( arr: T[] ): T | null => arr....

May 22, 2022

Lambda Calculus

楔子 這是一個在計算機歷史用數學演化的方式,具有代表性的規律。 Lambda (λ) Calculus Function Abstraction 能夠用簡單的方式來呈現函數 λx.x^2 + 1 用 js 來表示 let res = x => x * x + 1 Function Application 何謂 β-reduction(beta reduction) ? 就是把「值」代入取得最後的計算結果 let res = (x => x * x + 1)(3) 但有些情況不符合 curry 的表示法 λxy.x*y 就應該轉換成 (λx.(λy.x*y)) 但其實 ( ) 是可以被簡化的 λx.λy.x*y 如果先代入一個數值 5 (λx.(λy.x*y)) (5) = (λy.5*y) 再代入 7 (λy.5*y)(7) = 35 用 javascript 來表示 function product(x, y) { return x * y; } product(5, 7) //retuns 35 // curry function product (x) { return function (y) { return x * y; } } 參考資料...

May 21, 2022

寫給想跳坑的 JS 新手(Part II): coding style

楔子 上一篇提到了 map filter reduce,這三個是最常見的也是最常用的使用方法,為了讓「程式碼」易讀,可以改造一下長相方便讓人看的懂在做什麼,至於怎做的就交給專業的人去優化改善就好。 所以先至少讓別人看的懂自已在寫的東西優先,試想看看,如果你是看 code 的人,「看的懂」vs 「要花一點點時間去細看」這二種,哪一種比較好讀? 先做到至少菜端出來看起來想吃,至於好不好吃就再說囉。嘿嘿嘿 程式碼的味道 用個最簡單的例子,把一個數字 x3 之後再 +1,但當數字是 5時就返回原值 f(1) = 1 * 3 + 1 f(5) = 5 來寫出這個 f 但我們用不同的長相來看看 撒尿牛丸全部攪在一起 這個應該是大部份的程式羅輯,就是把資料拆開來一個一個處理。 function f(x) { if(x !== 5) { return 3 * x + 1 } else { return x } } 點點點到天邊 這個 coding-style 就像你打開一個箱子把東西拿出來,「動作」後再放回去,依序處理。 let box = x => ({f: f => box(f(x)), x}) box(1) .f(multi3) .f(add1) // {f: ƒ f(), x: 4} box(5) ....

May 20, 2022

寫給想跳坑的 JS 新手(Part I): map filter reduce

楔子 身邊有些朋友有不少會想試著寫寫程式,常常坊間書翻一翻看到物件的東西,很快的就把書放下了,慢慢的也就失去興趣了。 但其實怎讓這些朋友開始可以有些動手做也能跑出一些結果,那種成就感會讓人慢慢的親近寫程式(coding),不可否認物件導向語言統治了軟體界,但光要先學會這個觀念可能就讓人却步了。 以前有部電影「張三峰」有句台詞,怎「張無忌」問,怎學會這部武功?「張三峰」說:「忘掉就好了」。 其實函數式語言的「入門」蠻簡單的,就像小時候的數學,函數吃一些變數,跑出來一個結果,用這個方式寫寫東西就可以做一些小實務的作品,也很有成就感。 就讓我們試試吧.. Declarative 宣告式 vs. Imperative 命令式 命令式(Imperative)白話文就是要用電腦的角度去思考,怎把答案做出來。 如果相要把一連串的資料去掉一些特定值(前提條件就要知道何謂 for-loop),示範的程式碼大概會長成下面的樣子 function filter(array) { let newArray = [] for (let index = 0; index < array.length; index++) { const element = array[index] if (element !== null && element !== undefined) { newArray[newArray.length] = element } } return newArray } // use case: filter([0, 1, undefined, 2, null, 3, 'four', '']) // [0, 1, 2, 3, 'four', ''] 但如果是所謂的宣告(Declarative)式,就是使用 filter 函數(知道 map/filter/reduce....

May 19, 2022

Monad Compose

楔子 今天再來進階一下改寫 Monad compose Monad 特徵 of: a => M(a) 也有人叫 lift 或 type lift map: map 的 f :: a => M(b) 會變成 M(M(b)) flatten: M(M(b)) => M(b) Monad 有 flapMap 的概念 flatMap = Map + flatten : f(a).flatMap(g) => M(b) const MyMonad = value => ({ flatMap: f => f(value), map (f) { return this.flatMap(a => Monad.of(f(a))), }, }) Monad.of = x => Monad(x) Monad(21).map( x => x * 2)....

May 18, 2022

Monad vs Promise

楔子 來試著說明何謂 monad 這其實是數學的一個名稱,但撇開那些艱深的道理,試試來用 Promise 的例子來說明看看。 Function Compose 最原始的 compose 的觀念就是把多個 function 做組合 const x = 20 const f = n => n * 2 const arr = Array.of(x) const result = arr.map(f) 例如 echo 就是吃二個參數回傳一個 function const echo = n => x => Array.from({length: n}).fill(x) console.log( [1,2,3].map( echo(3) ) ) 例如 flatMap 就是吃二個參數回傳一個 function const flatMap = (f, arr) => [].concat(...arr.map(f)) const echo = n => x => Array.from({length: n})....

May 17, 2022

lens laws

楔子 在 functional programming 中要進行對 store 的設定時,可以用 lens 的方式來進行設定,如果就像一個吸管直接定位來改變值,進行值也可以用函數來取代。 lens laws laws view(lens, set(lens, store, a)) = a 如果你改變了 store 某個值之後再立刻利用 lens 來取 store 的值,二個會相等(白話的意思就是你改變了 store 的值再拿出來看就是那個值) set(lens, b, set(lens, store, a)) = set(lens, b, store) 如果你改變了 store 的值為 a 又立馬改變值為 b,等同於直接改變值為 b(白話的意思就是你把一個值設了二次,最後的結果是第二次的值) set(lens, view(lens, store), store) = store 如果你用 lens 拿了某個值出來再同時 set 在 store 的 lens 位置的值,store 和原來的一致(白話文就是你取個 lens 的值拿出來的值再設到同一個 lens,該 store 維持不變) const view = (lens, store) => lens....

May 15, 2022

function mixins

楔子 在公司的專案開發中,程式總會愈長愈大,會慢慢的到了一個程度難以理解,在開發的過程中也慢慢開始把程式做一些模組化的動作。 在程式的抽像化過程中,應該有二大派系很當使用,就是物件導向 & 函數式編程。通常會蠻常出現二個關鍵字 繼承(inheritance) 組合(composition) Mixins “Favor object composition over class inheritance” the Gang of Four, “Design Patterns: Elements of Reusable Object Oriented Software” 有一種說法所謂的 mixins 就是像冰淇淋甜筒一樣,想吃什麼挖什麼口味,只要甜筒有那個味道功能,甜筒就只是一個載具而以。 Object composition 在 javascript 內,物件可以塞 function ,這時就要利用到 Object.assign 這個方法。 const chocolate = { hasChocolate: () => true } const caramelSwirl = { hasCaramelSwirl: () => true } const pecans = { hasPecans: () => true } const iceCream = Object.assign( {}, chocolate, caramelSwirl, pecans ) console....

May 13, 2022

升級 javascript 到 typescript

楔子 typescript 針對 javascript 有進行型別的補強,在 functional programming 的 lib 中,有 fp-ts 可以使用,不過個人覺的它有點複雜變的不太好用,它的型別有點太多了,先了解它的東西應該就飽了,那今天來試試改用小刀水平的 javascript 吧。 說明 先要熟悉一下 arrow function 的 typescript 有點不易閱讀(官網也這樣說) 這是一個取第一個值的簡單函數 let fst: (a: any, b: any) => any = (a, b) => a 如果套上括號(弄個特殊的括號 [ ] ),應該就可以比較好懂這個格式了。 let fst: [(a: any, b: any) => any] = (a, b) => a 比較容易理解的還是用純 function 來寫 function fst(a: any, b: any): any { return a } 如果再套上 Generic types 的表達格式 function fst<T,U>(a: T, b: U): T { return a } 接下來開始改造 lib 升級到 typescript 先從小的東西開始,如果原來的 javascript...

May 12, 2022