Go言語ぽい不動点演算子

//cat paraY.go
package main

import "fmt"

func p(v ...) { fmt.Println(v) }

func Para(a func (),b func ()) {
	go a();
	go b();
}

func dummy(x int,c chan int) {
	p(x,"in dummy");
}

func Y1(f func (func (int,chan int)) (func (int,chan int))) (func (int,chan int)) {
	
	return (func (x int,c chan int) {
		Para(
			func () { f(Y1(f))(x,c); },
			func () { f(dummy)(x,c); }
		);
	});

}

func main() {
	fact := Y1(func (proc func (int,chan int)) (func (int,chan int)) {
		return (func (x int,r chan int) {
			if x == 0 {
				r <- 1;
			}
			else {
				c := make(chan int);
				proc(x - 1,c);
				v := <- c;
				r <- x * v;
			}
		});
	});
	
	get := make(chan int);
	fact(10,get);
	p(<- get);
}

call-by-valueな言語では(Go言語はCBVです)、お手軽Yコンビネータ

Y f = f (Y f)

の形では書けません。(Haskellでは出来ます)

ですが、Go言語はgoroutineがあるので、

f(dummy),f(f),f(f(f)),f(f(f(f))),...,

のように関数を作ってあげる事が出来ます。


というソレを書いてみました。

ちょっと辛いのは、やはり型が値の所に現れてしまうので見た目が辛いという事ですかね。

typeを使えば取りあえずは避けられますけど・・・。