【问题标题】:Can some explain me how this solution works有人能解释一下这个解决方案是如何工作的吗
【发布时间】:2018-08-16 20:18:09
【问题描述】:

我通过反复试验解决了以下问题,但仍然没有正确理解我是如何做到的。

有一个函数缺点:const cons = (x, y) => f => f(x, y);

将值存储到变量对:const pair = cons(5, 3);

创建两个函数 car 和 cdr ,它们每个都会返回一个参数。

car(pair); // 5

cdr(pair); // 3

我的解决方案:

const car = pair => pair((x, y) => x);

const cdr = pair =>pair((x,y) => y);

const cons = (x, y) => f => f(x, y);

const pair = cons(5, 3);

const car = pair => pair((x, y) => x);

const cdr = pair => pair((x,y) => y);

const carTest = car(pair);
const cdrTest = cdr(pair);

console.dir(carTest);
console.dir(cdrTest);

【问题讨论】:

  • 我有时发现将箭头函数重写为常规函数很有帮助——它使闭包和返回值更容易理解(至少对我而言)。
  • 做到了。解决练习仍然有问题。

标签: javascript functional-programming


【解决方案1】:

这里cons(x, y)构造了一个pair,而car(pair)cdr(pair)返回firstlast元素pair

pair 也是一个function,它将函数作为输入并将输入函数的输出返回为xy


为了更好地解释您的解决方案:

const car = pair => pair((x, y) => x);

将箭头函数重写为常规函数:

function car(pair){

   var result= pair(
   function temp(x, y){
     return x;
    }
   );
   return result;
}

这里

1. Car函数将pair作为argument

const car = pair =>........;

2. pair 是一个 function,它接受另一个函数作为输入,其中 2 arguments 有 5 ,3 作为 value

......=> 对(......;

3.这2个values作为argument传递并在x, y中赋值,x作为结果返回。

.................((x, y) => x);


const cons = (x, y) => f => f(x, y);

const pair = cons(5, 3);

//const car = pair => pair((x, y) => x);
const cdr = pair => pair((x,y) => y);

function car(pair){
   
   var result= pair(
   function temp(x, y){
     return x;
    }
   );
   return result;
}
const carCall = car(pair);
const cdrCall = cdr(pair);

console.log(carCall);
console.log(cdrCall);

【讨论】:

    【解决方案2】:

    很难回答你是如何“做到的”,因为你似乎对答案有些迷茫。

    当你还不知道答案时,通过发明一个从未如此线性的思维过程来作弊,一种方法是首先仔细观察cons 做了什么:

    const cons = (x, y) => (f => f(x, y))
    

    它需要两个东西,(x, y),然后返回一个函数。
    此函数接受另一个函数f,并将该函数应用到(x, y) 的结果返回给cons

    对于car,我们要提取这样一对的第一个元素。

    要选择(x, y)的第一个元素,我们可以将它传递给函数

    const first = (x, y) => x 
    

    由于 pair 是一个接受一个函数并将该函数应用于其元素的东西,因此将 first 传递给 pair 应该选择它的第一个元素:

    (cons(3,5))(first)
    

    是 3。

    但是现在语法“倒退”了,所以我们使用另一个函数来扭转它:

    const car = p => p(first)
    

    代入first的定义:

    const car = p => p((x,y) => x)  
    

    同样的过程导致cdr


    要确切了解正在发生的事情,您有

    const pair = cons(5, 3);
    

    代入cons的定义:

    const pair = f => f(5, 3);
    

    car 应用到f => f(5,3) 并继续替换:

    (pair => pair((x, y) => x)) (f => f(5,3))
    
    -->
    
    (f => f(5,3)) ((x, y) => x))
    
    --> 
    
    ((x, y) => x)) (5,3)
    
    --> 5
    

    【讨论】:

    • 第一部分带来了一些启示。知道在哪里可以找到类似的练习吗?
    • 我建议深入研究 lambda 演算。有趣的练习可能是将布尔值表示为函数并实现条件,或者将整数表示为函数(不允许语言级别的数字)并实现加法。
    • 基本上是这样的lisp/scheme?还是你的意思是别的?哈斯克尔呢?我为 Haskell 找到了更多资源,但我准备尽一切努力在 FP 中变得更好
    • 我的字面意思是 lambda 演算,但其中任何一个都应该有效。 (不过,我会推荐 Racket。Lispy 语法、漂亮的语言、有用的 IDE、有用的社区。)
    【解决方案3】:

    查看类型:

    // cons :: (a, b) -> ((a, b) -> r) -> r
    const cons = (x, y) => f => f(x, y);
    
    // pair :: ((Number, Number) -> r) -> r
    const pair = cons(5, 3);
    
    // fst :: (a, b) -> a
    const fst = (x, y) => x;
    
    // snd :: (a, b) -> b
    const snd = (x, y) => y;
    
    // car :: (forall r. ((a, b) -> r) -> r) -> a
    const car = pair => pair(fst);
    
    // cdr :: (forall r. ((a, b) -> r) -> r) -> b
    const cdr = pair => pair(snd);
    

    如您所见,cons 采用两个值 x :: ay :: b 并创建一对。对是一个函数,它将 另一个 函数作为输入,并通过将 输入函数 应用到 xy 来返回 输入函数 的输出。这使我们可以做一些事情,比如添加对的值(即cons(5, 3)((x, y) => x + y),其计算结果为8)。

    现在,如果我们将该对应用于函数fstsnd,那么我们将分别得到该对的第一个值和第二个值。因此,carcdr 只需将输入对分别应用于函数 fstsnd。希望对您有所帮助。

    【讨论】:

    • 这是基于 Haskell 的答案吗?
    • 是的,是的。
    • 根据您的个人资料,您了解 Scheme 和 Haskell。根据您的意见,对于初学者 javascript 程序员以便在 FP 中取得好成绩更有利?
    • 既然您已经了解 JavaScript,我建议您使用 Haskell。 Scheme 类似于 JavaScript。因此,您通过学习 Haskell 比通过学习 Scheme 了解更多关于 FP 的知识。有一本很棒的在线书籍叫Learn You A Haskell。你应该读一下。
    【解决方案4】:
    const cons = (x, y) => f => f(x, y);
    const pair = cons(5, 3);
    // pair = f => f(5, 3)
    const car = pair => pair((x, y) => x);
    // replace f as (x, y) => x
    // then ((x, y) => x)(5, 3)
    

    【讨论】:

    • 虽然此代码 sn-p 可能是解决方案,但包含解释确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    猜你喜欢
    • 2023-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2023-01-18
    • 1970-01-01
    • 2019-10-24
    • 2016-06-13
    • 1970-01-01
    相关资源
    最近更新 更多