如何递归定义广义投影函数?

时间:2018-07-29 09:11:53

标签: javascript recursion functional-programming combinatory-logic

Projection functions,例如id( 1 P 1 )和const( 2 P 1 )在函数å¼ç¼–程中éžå¸¸æœ‰ç”¨ã€‚但是,有时您需è¦æ›´å¤æ‚的投影功能,例如 5 P 4 。您å¯ä»¥æ‰‹åŠ¨å°†å…¶ä»¥ç‚¹åæ ·å¼ç¼–写为a => b => c => d => e => d,但这很ä¹å‘³ä¸”ä¸æ˜“读。因此,能够写proj(5)(4)会更好。这是我目å‰åœ¨JavaScript中定义此广义投影函数的方å¼ï¼š

const proj = n => m => curry(n, (...args) => args[m - 1]);

const curry = (n, f, args = []) => n > 0 ?
    x => curry(n - 1, f, args.concat([x])) :
    f(...args);

console.log(proj(5)(4)("a")("b")("c")("d")("e")); // prints "d"

如您所è§ï¼Œprojçš„è¿™ç§å®žçŽ°æ˜¯ä¸€ä¸ªhack,因为它利用了å¯å˜å‚数。因此,它ä¸èƒ½ç›´æŽ¥ç¿»è¯‘æˆAgda或Idris之类的语言(由于ä¾èµ–的类型,其中的通用投影函数实际上是å¯é”®å…¥çš„)。那么,如何以一ç§å¯ä»¥å°†å…¶ç›´æŽ¥è½¬æ¢ä¸ºAgdaçš„æ–¹å¼æ¥é€’归定义广义投影函数呢?

1 个答案:

答案 0 :(得分:0)

所有投影函数都å¯ä»¥åˆ†è§£ä¸ºä»¥ä¸‹ä¸‰ä¸ªç»„åˆå™¨ï¼š

I :: a -> a
I x = x

K :: a -> b -> a
K x y = x

C :: (a -> c) -> a -> b -> c
C f x y = f x

使用这三个组åˆå™¨ï¼Œæˆ‘们å¯ä»¥å®šä¹‰å„ç§æŠ•å½±å‡½æ•°ï¼Œå¦‚下所示:

┌─────┬──────────┬──────────┬──────────┬──────────┬─────────────â”
│ n\m │     1    │     2    │     3    │     4    │      5      │
├─────┼──────────┼──────────┼──────────┼──────────┼─────────────┤
│  1  │      I   │          │          │          │             │
│  2  │      K   │     KI   │          │          │             │
│  3  │     CK   │     KK   │   K(KI)  │          │             │
│  4  │   C(CK)  │   K(CK)  │   K(KK)  │ K(K(KI)) │             │
│  5  │ C(C(CK)) │ K(C(CK)) │ K(K(CK)) │ K(K(KK)) │ K(K(K(KI))) │
└─────┴──────────┴──────────┴──────────┴──────────┴─────────────┘

如您所è§ï¼Œè¿™é‡Œæœ‰ä¸€ä¸ªé€’归模å¼ï¼š

proj 1 1 = I
proj n 1 = C (proj (n - 1) 1)
proj n m = K (proj (n - 1) (m - 1))

请注æ„,K = CI起作用的原因是proj 2 1。将其直接转æ¢ä¸ºJavaScript:

const I = x => x;
const K = x => y => x;
const C = f => x => y => f(x);

const raise = (Error, msg) => { throw new Error(msg); };

const proj = n => n === 1 ?
    m => m === 1 ? I : raise(RangeError, "index out of range") :
    m => m === 1 ? C(proj(n - 1)(1)) : K(proj(n - 1)(m - 1));

console.log(proj(5)(4)("a")("b")("c")("d")("e")); // prints "d"

我将ä¿ç•™å®ƒä½œä¸ºç»ƒä¹ ï¼Œè®©æ‚¨äº†è§£æ­¤å‡½æ•°çš„ä¾èµ–类型。