github.com/l3x/learn-fp-go@v0.0.0-20171228022418-7639825d0b71/4-purely-functional/ch10-monads/03_y_combinator/main.go (about)

     1  package main
     2  
     3  import "fmt"
     4  
     5  type Func func(int) int
     6  type FuncFunc func(Func) Func
     7  type RecursiveFunc func (RecursiveFunc) Func
     8  
     9  // @tco yCombinator implements the lambda expression that
    10  // enables composition of unpure components in our workflow
    11  func yCombinator(f FuncFunc) Func {
    12      g := func(r RecursiveFunc) Func {
    13          return f(func(x int) int {
    14              return r(r)(x)
    15          })
    16      }
    17      return g(g)
    18  }
    19  
    20  func fibFuncFunc(f Func) Func {
    21      return func(x int) int {
    22          if x == 0 {
    23              return 0
    24          } else if x <= 2 {
    25              return 1
    26          } else {
    27              return f(x-2) + f(x-1)
    28          }
    29      }
    30  }
    31  
    32  func Recurse(f FuncFunc) Func {
    33      return func(x int) int {
    34          return f(Recurse(f))(x)
    35      }
    36  }
    37  
    38  func fib(x int) int {
    39      if x == 0 {
    40          return 0
    41      } else if x <= 2 {
    42          return 1
    43      } else {
    44          return fib(x-2) + fib(x-1)
    45      }
    46  }
    47  
    48  func main() {
    49      yCombo := yCombinator(fibFuncFunc)
    50      recurse := Recurse(fibFuncFunc)
    51      for x := 0; x < 50; x++ {
    52          fmt.Printf("yCombo(%d) = %d\n", x, yCombo(x))
    53          fmt.Printf("recurse(%d) = %d\n", x, recurse(x))
    54          fmt.Printf("plainRe(%d) = %d\n", x, fib(x))
    55          fmt.Println("---")
    56      }
    57  }