# 代數資料型態

December 14, 2021

## List 有頭有尾

``````let con = head => tail => [head, tail];
``````

## 建構 List

``````let nil = [undefined, undefined];
``````

``````let lt1 = con(1)(nil);
``````

``````let lt2 = con(2)(lt1);
``````

``````let head = ([h, _]) => h;
let tail = ([_, t]) => t;
let isEmpty = lt => head(lt) === undefined;
``````

``````let rcon = tail => head => head === undefined ? tail : rcon(con(head)(tail));
``````

`rcon(nil)(1)(2)(3)()` 做的會是 `con` 的相反動作，這就是為什麼叫它 `rcon` 的原因，為了最後能建立 List，最後若呼叫函式時沒有指定元素，就將建立的 List 傳回而不再是傳回函式。

``````let rev = r => l => isEmpty(l) ? r : rev(con(head(l))(r))(tail(l));
let reverse = lt => rev(nil)(lt);
``````

``````let elems = rcon(nil);
let list = elems => reverse(elems());
``````

``````let lt = list(elems(1)(2)(3));
``````

## 流程抽象化

``````let len = lt => isEmpty(lt) ? 0 : 1 + len(tail(lt));
``````

`len(list(elems(1)(2)(3)))` 會傳回 3 的結果。如果要加總一個 List 呢？

``````let sum = lt => isEmpty(lt) ? 0 : head(lt) + sum(tail(lt));
``````

`sum(list(elems(1)(2)(3)))` 會傳回 6 的結果。看起來還不錯，接著想想看，怎麼定義一個 `addOne` 函式，可以對傳入 List 中每個元素加一後傳回新 List 呢？

``````let addOne = lt => isEmpty(lt) ? nil : con(head(lt) + 1)(addOne(tail(lt)));
``````

``````let map = lt => f => isEmpty(lt) ? nil : con(f(head(lt)))(map(tail(lt))(f));
``````

``````let greaterThanThree = lt  => isEmpty(lt) ? nil :
greaterThanThree(tail(lt));
``````

``````let filter = lt => f => isEmpty(lt) ? nil :
filter(tail(lt))(f);
``````

## 更多匿名函式

``````y(map => lt => f => isEmpty(lt) ? nil : con(f(head(lt)))(map(tail(lt))(f)))(list(elems(1)(2)(3)))(elem => elem - 1)
``````

``````y(map => lt => f => (lt => head(lt) === undefined)(lt) ? nil : con(f(head(lt)))(map(tail(lt))(f)))(list(elems(1)(2)(3)))(elem => elem - 1)
``````

``````(f => (x => f(n => x(x)(n)))(x => f(n => x(x)(n))))(map => lt => f => (lt => head(lt) === undefined)(lt) ? nil : con(f(head(lt)))(map(tail(lt))(f)))(list(elems(1)(2)(3)))(elem => elem - 1)
``````

``````(f => (x => f(n => x(x)(n)))(x => f(n => x(x)(n))))(map => lt => f => (lt => head(lt) === undefined)(lt) ? nil : con(f(head(lt)))(map(tail(lt))(f)))((elems => (lt => (f => (x => f(n => x(x)(n)))(x => f(n => x(x)(n))))(rev => r => l => (lt => head(lt) === undefined)(l) ? r : rev(con(head(l))(r))(tail(l)))(nil)(lt))(elems()))((f => (x => f(n => x(x)(n)))(x => f(n => x(x)(n))))(rcon => tail => head => head === undefined ? tail : rcon(con(head)(tail)))(nil)(1)(2)(3)))(elem => elem - 1)
``````