# 簡單是非

December 15, 2021

## yes/no

``````let yes = x => _ => x;
let no = _ => y => y;
``````

``````let not = b => b(no)(yes);
``````

## 重構

``````// 這一行還不會真的運算出結果
let lazy_len = len(con(\$2)(con(\$1)(nil)));

// 這一行才會真的求值
console.log(natural(lazy_len(no_use)));
``````

``````let len = l => when(isEmpty(l))
(_ => \$0)
``````

`con(\$2)(con(\$1)(nil))` 傳入後，`isEmpty(l)` 會是 `no`，因此傳回的是 `_ => add(\$1)(len(tail(con(\$2)(con(\$1)(nil)))))`，實際運行求值時，必然會要求 `len(tail(con(\$2)(con(\$1)(nil))))` 的結果，也就是 `len(con(\$1)(nil))`，此時傳回 `_ => add(\$1)(len(tail(con(\$1)(nil))))`，也就是最後運算的結果，其實就是 `add(\$1)(_ => add(\$1)(len(tail(con(\$1)(nil)))))` 進行運算的結果！嗯？哪邊怪怪的？

`len` 的定義，遞迴終止時的 `_ => \$0` 沒有被傳回，並非符合遞迴終止條件才傳回結果，無巧不巧地，`add(\$1)(_ => add(\$1)(len(tail(con(\$1)(nil)))))` 是可以被 `natural` 計算為 1 的結果，無論傳入多長的 List，結果一定顯示 1。

``````let len = l => when(isEmpty(l))
(_ => \$0)
``````

``````let len = l => when(isEmpty(l))
(_ => \$0)
``````

``````let y = f => (x => f(n => x(x)(n)))(x => f(n => x(x)(n)));

let unit = _ => _;
let no_use = unit;

let yes = x => _ => x;
let no = _ => y => y;
let when = unit;

let not = b => b(no)(yes);

let pair = l => r => f => f(l)(r);
let left = p => p(l => _ => l);
let right = p => p(_ => r => r);

let nil = _ => yes;
let con = h => t => pair(h)(t);
let tail = right;

let is_nil = l => l(_ => _ => no);
let isEmpty = is_nil;

let \$0 = _ => x => x;
let \$1 = f => x => f(x);
let \$2 = f => x => f(f(x));
let \$3 = f => x => f(f(f(x)));
let is_\$0 = n => n(_ => no)(yes);

let \$\$ = _ => _ => yes;
let is_\$\$ = n => n(_ => no)(no);

let succ = n => f => x => f(n(f)(x));
let add = m => n => n(succ)(m);

let pair_succ = p => pair(right(p))(succ(right(p)));
let prev = n => left(n(pair_succ)(pair(\$0)(\$0)));
let sub = m => n => n(prev)(m);

let len = y(len => l => when(isEmpty(l))
(_ => \$0)

let sum = y(sum => l => when(isEmpty(l))
(_ => \$0)

let rcon = y(rcon => t => h => when(is_\$\$(h))
(_ => t)
(_ => rcon(con(h)(t)))(no_use));

let rev = y(rev => r => l => when(isEmpty(l))
(_ => r)

let reverse = l => rev(nil)(l);

let elems = rcon(nil);

let list = es => reverse(es(\$\$));

let map = y(map => l => f => when(isEmpty(l))
(_ => nil)

let lt = list(elems(\$1)(\$2)(\$3));
let lt2 = map(lt)(elem => sub(elem)(\$1));

console.log(natural(len(lt)));
console.log(natural(sum(lt)));
console.log(array(lt2));

function natural(n) {
return n(i => i + 1)(0);
}

function array(lt) {
function arr(acc, l) {
return when(isEmpty(l))
(_ => acc)