How does `const` turn multi-parameter functions iterable by the `fix` fixed-point combinator?

31 Views Asked by At

Have been struggling with fix for years, and this made my head scratch again:

fix = f: let fixpoint = f fixpoint; in fixpoint
const = a: b: a

( fix ( const ( a: b:    a + b    ))) 1 2    #=> 3
( fix ( const ( a: b: c: a + b + c))) 1 2  3 #=> 6

For some reason I can't wrap my head around this.

1

There are 1 best solutions below

0
toraritte On

Turns out, I was massively overthinking this... To quote Nathan Faubion:

A fixed-point combinator gives control to some higher-order function in such a way that it progresses recursively.

This is probably evident, but looks like I wasn't able to put two and two together.

const above can be thought of simply wrapping an input function,

sum = a: b: a = b
const sum  #<~> x: sum

and the examples can be rewritten in the following forms:

( fix ( const sum            )) 1 2   #=> 3

( fix ( const ( a: b: a + b ))) 1 2   #=> 3

( fix (      x: a: b: a + b ))) 1 2   #=> 3

( fix (      x: sum          )) 1 2   #=> 3

Writing out the evaluation steps:

fix f = f( f( f( ... )))

fix (x: sum) = (x: sum) ( (x: sum) ( ... )) = sum
    ---f---- = ---f---- ( ---f---- ( ... ))

To belabor the point, input x is literally ignored:

( fix ( x: sum )) 1 2

   ┏━━━━━━━━━━━━━━━━━━┓
   ∨          --------┃-------
( (x: sum) (  (x: sum) ( ... )  )  ) 1 2
  -----------┃-------------------
             ┃
             ∨
         (  sum  ) 1 2

Putting the PureScript version here, because it looks slightly different as PureScript is strict, unlike Nix:

fix f a = f (fix f) a
const a b = a

( fix ( const $ \x y   -> x + y     )) 1 2   --> 3
( fix ( const $ \x y z -> x + y + z )) 1 2 3 --> 6

(Again, see Nathan's reply for more details.)