在JavaScript中的y组合 [英] y-combinator in javascript

查看:115
本文介绍了在JavaScript中的y组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  const y = f =>我已经在js中构建了一个y-combinator。 {const g = self => x => F(自(个体))(X);返回g(g);} 

并且我像这样简化了这段代码

  const y = f => {const g = self => F(自(个体)); return g(g);} 

这会得到无限递归。
这两个版本有什么区别?

解决方案

如果您不了解两者的区别,我会惊讶于您实际构建了它们。尽管如此,也许证明两者之间差异的最好方法是遵循他们的评估。

  const y = f => {
const g = self => x => f(self(self))(x)
return g(g)
}

y(z)...
//(self => x (self(self))(x))(self => x => z(self(self))(x))...
//返回:
/ / x => z(自己=> x1 => z(self(self))(x1))(self => x2 => z(self(self))(x2)))(x)

好的,所以 y(z)(其中 z 是一些函数,没关系)返回一个函数 x => ...... 。现在,我们将它与第二个定义进行比较。
$ b $ b

  const y = f => {
const g = self => f(self(self))
return g(g)
}

y(z)...
//(self => z(self (self(self))(self(self))(self(self))(self(self)) ))...
// z(z((self(自我))> z(self(self)))(self => z(self(self)))))...
(self(self(self)))(self => z(self(self))))))...
// z(z(z (self(self(self)))(self => z(self(self)))))))...
// ...并且on和on

所以 y(z)永不终止 - 至少在使用应用性命令评估的JavaScript中 - 其中函数参数在被调用函数应用之前被评估




交替Y-组合

这里我们可以从头开始构建一个Y组合器

  //标准定义
const Y = f => f(Y(f))

//防止立即无限递归顺序语言(JS)
const Y = f => f( x => Y(f)(x)

//使用U combinator删除对自己的引用
const U = f(f)
常数Y = U(h => f => f(x)> h(h)(f)(f


让我们来测试它

const U = f =>>

 f => f(x => h(h)(f)(x)))// range :: Int  - > Int  - > [x] = y(f => acc => x => y => x> y?acc:f([... acc,x])(x + 1) )([])// fibonacci :: Int  - > Intconst fibonacci = Y(f => a => b => x => x === 0→a:f(b)(a + b)(x-1))(0) console.log(range(0)(10).map(fibonacci))// [0,1,1,2,3,5,8,13,21,34,55]  



或者我最近的最爱

  //简化的Yconst Y = f => x => f(Y(f))(x)// range :: Int  - > Int  - > [x] = y(f => acc => x => y => x> y?acc:f([... acc,x])(x + 1) )([])// fibonacci :: Int  - > Intconst fibonacci = Y(f => a => b => x => x === 0→a:f(b)(a + b)(x-1))(0) console.log(range(0)(10).map(fibonacci))// [0,1,1,2,3,5,8,13,21,34,55]  


I have built a y-combinator in js like this

const y = f => { const g = self => x => f(self(self))(x); return g(g);}

and I simplified this code like this

 const y = f => { const g = self => f(self(self)); return g(g);}

this get an infinite recursion. What's the difference between these two versions?

解决方案

If you don't understand the difference between the two, I would be surprised that you actually built them. Nevertheless, perhaps the best way to demonstrate the difference between the two, is to follow their evaluation

const y = f => {
  const g = self => x => f(self(self))(x)
  return g(g)
}

y (z) ...
// (self => x => z(self(self))(x)) (self => x => z(self(self))(x)) ...
// returns:
// x => z((self => x1 => z(self(self))(x1))(self => x2 => z(self(self))(x2)))(x)

Ok, so y(z) (where z is some function, it doesn't matter) returns a function x => .... Until we apply that function, evaluation stops there.

Now let's compare that to your second definition

const y = f => {
  const g = self => f(self(self))
  return g(g)
}

y (z) ...
// (self => z(self(self))) (self => z(self(self)))
// z((self => z(self(self)))(self => z(self(self)))) ...
// z(z((self => z(self(self)))(self => z(self(self))))) ...
// z(z(z((self => z(self(self)))(self => z(self(self)))))) ...
// z(z(z(z((self => z(self(self)))(self => z(self(self))))))) ...
// ... and on and on

So y (z) never terminates – at least in JavaScript which uses applicative order evaluation – where function arguments are evaluated before the called function is applied


Alternate Y-combinators

Here we can build a Y-combinator from the ground up

// standard definition
const Y = f => f (Y (f))

// prevent immediate infinite recursion in applicative order language (JS)
const Y = f => f (x => Y (f) (x))

// remove reference to self using U combinator
const U = f => f (f)
const Y = U (h => f => f (x => h (h) (f) (x)))

Let's test it out

const U = f => f (f)

const Y = U (h => f => f (x => h (h) (f) (x)))

// range :: Int -> Int -> [Int]
const range = Y (f => acc => x => y =>
  x > y ? acc : f ([...acc,x]) (x + 1) (y)) ([])

// fibonacci :: Int -> Int
const fibonacci = Y (f => a => b => x =>
  x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
  
console.log(range(0)(10).map(fibonacci))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]

Or my recent favourite

// simplified Y
const Y = f => x => f (Y (f)) (x)

// range :: Int -> Int -> [Int]
const range = Y (f => acc => x => y =>
  x > y ? acc : f ([...acc,x]) (x + 1) (y)) ([])

// fibonacci :: Int -> Int
const fibonacci = Y (f => a => b => x =>
  x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
  
console.log(range(0)(10).map(fibonacci))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]

这篇关于在JavaScript中的y组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆