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 }