// run // Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import "fmt" // Y is the Y-combinator based on https://dreamsongs.com/Files/WhyOfY.pdf func Y[Endo ~func(RecFct) RecFct, RecFct ~func(T) R, T, R any](f Endo) RecFct { type internal[RecFct ~func(T) R, T, R any] func(internal[RecFct, T, R]) RecFct g := func(h internal[RecFct, T, R]) RecFct { return func(t T) R { return f(h(h))(t) } } return g(g) } func main() { fct := Y(func(r func(int) int) func(int) int { return func(n int) int { if n <= 0 { return 1 } return n * r(n-1) } }) want := 3628800 if got := fct(10); got != want { msg := fmt.Sprintf("unexpected result, got: %d, want: %d", got, want) panic(msg) } }