Created
August 16, 2019 21:36
-
-
Save dhil/cdc4bebda9303d236179ec9bfafc6fb9 to your computer and use it in GitHub Desktop.
Typing the Y combinator in Java.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Typing the Y combinator in Java (tested with OpenJDK 11.0.4). | |
// $ javac Y.java | |
// $ java Y | |
// 720 | |
// Succ(Succ(Succ(Succ(Succ(Succ(Zero)))))) | |
import java.util.function.Function; | |
// A typed implementation of the Y-combinator. | |
public class Y { | |
// The trick is to use a recursive type. | |
interface Fix<A> extends Function<Fix<A>, A> {} | |
// Y : ((A -> B) -> A -> B) -> A -> B. | |
public static <A, B> Function<A,B> Y(final Function<Function<A,B>,Function<A,B>> f) { | |
Function<Fix<Function<A,B>>,Function<A,B>> abs = | |
(final Fix<Function<A,B>> x) -> | |
(final A a) -> | |
f.apply(x.apply(x)).apply(a); | |
Fix<Function<A,B>> arg = | |
(final Fix<Function<A,B>> x) -> | |
(final A a) -> | |
f.apply(x.apply(x)).apply(a); | |
return abs.apply(arg); | |
} | |
// Evaluate some examples. | |
public static void main(String[] args) { | |
// Factorial. | |
Function<Function<Integer,Integer>,Function<Integer,Integer>> fact = | |
(final Function<Integer, Integer> self) -> | |
(final Integer n) -> | |
n == 0 ? 1 : n * self.apply(n-1); | |
Integer result = Y(fact).apply(6); | |
System.out.println(result.toString()); | |
// Conversion of Integer to Nat. | |
Function<Function<Integer,Nat>,Function<Integer,Nat>> int2nat = | |
(final Function<Integer,Nat> self) -> | |
(final Integer n) -> | |
n == 0 ? new Zero() : new Succ(self.apply(n-1)); | |
Nat natural = Y(int2nat).apply(6); | |
System.out.println(natural.toString()); | |
} | |
// A representation of natural numbers. | |
public interface Nat {} | |
public static class Zero implements Nat { | |
public Zero() {} | |
public String toString() { return "Zero"; } | |
} | |
public static class Succ implements Nat { | |
Nat n; | |
public Succ(Nat n) { this.n = n; } | |
public String toString() { | |
return "Succ(" + n.toString() + ")"; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment