Quick actions

cmd+k|ctrl+k

Navigation

Languages

Y Combinator

Snippet info

Language

JavaScript

Visibility

public

Author

homam

Created

2016-04-15T12:40:09Z

Updated

2016-04-15T14:09:44Z

// utility range function, creates a list of [0, 1, 2, ..., i]
const range = i => [...Array(i).keys()]

// fixed point, Y combinator (proof at the end of the code)
const fix = f =>
  (g => z => f(g(g))(z)) (g => z => f(g(g))(z))


// open recursive definition of factorial funciton
// note that x is a funciton
// h is full factorial function if x is full factorial function
// h(h(h(h(...)))) is the full factorial function
let h = x => n => n === 0 ? 1 : n * x(n - 1)

// utility function used later
let makeFi = (f, i) =>
  i === 0 ? f(undefined) : f(makeFi(f, i-1))

// utility function used later  
let makeFiName = (gname, g, i) => {
  if(i === 0) {
    return {name: `${gname}(undefined)`, f: g(undefined)}
  } else {
    let {name, f} = makeFiName(gname, g, i-1)
    return {name: `${gname}(${name})`, f: g(f)}
  }
}


// applying h in itself multiple times to converge to factorial
let h0 = h(undefined)
let h1 = h(h(undefined))
let h2 = h(h(h(undefined)))

console.log("h0(0) = ", h0(0))
console.log("h1(1) = ", h1(1))
console.log("h2(2) = ", h2(2))

console.log("...")

// makeFi utility is used to apply f five times on itself
const h5 = makeFi(h, 5)
console.log("h5(5) = ", h5(5))

console.log("-----")



// check the output
const fs = range(10).map(i => ({i: i, f: makeFiName('h', h, i)}))

const fit = ({name, f}, i) => j => {
    const func = `h${i}(${j}) = ${name}(${j})`
    try {
        console.log(`${func} = ${f(j)}`)
        fit({name, f}, i)(j + 1)
    } catch (ex) {
        console.log(`${func} = undefined`)
    }
}

fs.forEach(({i, f}) => {
    fit(f, i)(0)
    console.log("-----")
})

// finally factorial is f(h) = h(fix(h)) = h(h(fix(h))) = h(h(h(fix(h)))) = ...
const fact = fix(h)
console.log("fact(10) = ", fact(10))
console.log("fact(100) = ", fact(100))


/*
proof: fix(h) = h(fix(h)) = h(h(fix(h))) == ...

fix = f =>
  (g => z => f(g(g))(z)) (g => z => f(g(g))(z))

fix(h)

(f =>
  (g => z => f(g(g))(z)) (g => z => f(g(g))(z))
)(h)

// apply h
(g => z => h(g(g))(z)) (g => z => h(g(g))(z))

z => h((g => z => h(g(g))(z))((g => z => h(g(g))(z))))(z)

// beta reduction
h((g => z => h(g(g))(z))((g => z => h(g(g))(z))))

// just look at it!
h((g => z => h(g(g))(z)) ((g => z => h(g(g))(z))))

h(fix(h))

*/

INFO