- interface Func<A, B> {
- B apply(final A arg);
- }
- abstract class Dir<A, B> {
- public Dir() {}
- abstract public Func<Func<String, A>, Func<String, B>> format();
- }
- class DLit<A> extends Dir<A, A> {
- private String s;
- public DLit(String s) {
- this.s = s;
- }
- public Func<Func<String, A>, Func<String, A>> format() {
- return new Func<Func<String, A>, Func<String, A>>() {
- public Func<String, A> apply(final Func<String, A> cont) {
- return new Func<String, A>() {
- public A apply(final String out) {
- return cont.apply(out + s);
- }
- };
- }
- };
- }
- }
- class DInt<A> extends Dir<A, Func<Integer, A>> {
- public DInt() {}
- public Func<Func<String, A>, Func<String, Func<Integer, A>>> format() {
- return new Func<Func<String, A>, Func<String, Func<Integer, A>>>() {
- public Func<String, Func<Integer, A>> apply(final Func<String, A> cont) {
- return new Func<String, Func<Integer, A>>() {
- public Func<Integer, A> apply(final String out) {
- return new Func<Integer, A>() {
- public A apply(Integer i) {
- return cont.apply(out + i.toString());
- }
- };
- }
- };
- }
- };
- }
- }
- class DStr<A> extends Dir<A, Func<String, A>> {
- public DStr() {}
- public Func<Func<String, A>, Func<String, Func<String, A>>> format() {
- return new Func<Func<String, A>, Func<String, Func<String, A>>>() {
- public Func<String, Func<String, A>> apply(final Func<String, A> cont) {
- return new Func<String, Func<String, A>>() {
- public Func<String, A> apply(final String out) {
- return new Func<String, A>() {
- public A apply(String s) {
- return cont.apply(out + s);
- }
- };
- }
- };
- }
- };
- }
- }
- class DCon<A, B, C, D> extends Dir<C, B> {
- private Dir<A, B> d1;
- private Dir<C, A> d2;
- public DCon(Dir<A, B> d1, Dir<C, A> d2) {
- this.d1 = d1;
- this.d2 = d2;
- }
- public Func<Func<String, C>, Func<String, B>> format() {
- return new Func<Func<String, C>, Func<String, B>>() {
- public Func<String, B> apply(final Func<String, C> cont) {
- return new Func<String, B>() {
- public B apply(final String out) {
- return d1.format().apply(d2.format().apply(cont)).apply(out);
- }
- };
- }
- };
- }
- }
- class SafeFormatter {
- public static <A> A format(Dir<String, A> d) {
- return d.format().apply(new Func<String, String>() {
- public String apply(final String a) {
- return a;
- }
- }).apply("");
- }
- public static <A> Dir<A, A> newDLit(String s) {
- return new DLit<A>(s);
- }
- public static <A> Dir<A, Func<Integer, A>> newDInt() {
- return new DInt<A>();
- }
- public static <A> Dir<A, Func<String, A>> newDStr() {
- return new DStr<A>();
- }
- public static <A, B, C, D> Dir<C, B> newDCon(Dir<A, B> d1, Dir<C, A> d2) {
- return new DCon<A, B, C, D>(d1, d2);
- }
- public static void main(String[] args) {
- //型安全なSystem.out.printf("hello, %s!", "world")を表現している。
- Dir<Func<String, String>, Func<String, String>> d1 = newDLit("hello, ");
- Dir<String, Func<String, String>> d2 = newDStr();
- Dir<String, String> d3 = newDLit("!");
- System.out.println(format(newDCon(newDCon(d1, d2), d3)).apply("world"));
- //System.out.println(format(newDCon(newDCon(d1, d2), d3)).apply(123)); //String以外の型はコンパイルエラー
- //型安全なSystem.out.printf("a: %d b: %d c: %d", 1, 2, 3)を表現している。
- Dir<Func<Integer, Func<Integer, Func<Integer, String>>>,
- Func<Integer, Func<Integer, Func<Integer, String>>>> d4 = newDLit("a: ");
- Dir<Func<Integer, Func<Integer, String>>,
- Func<Integer, Func<Integer, Func<Integer, String>>>> d5 = newDInt();
- Dir<Func<Integer, Func<Integer, String>>,
- Func<Integer, Func<Integer, String>>> d6 = newDLit(" b: ");
- Dir<Func<Integer, String>,
- Func<Integer, Func<Integer, String>>> d7 = newDInt();
- Dir<Func<Integer, String>, Func<Integer, String>> d8 = newDLit(" c: ");
- Dir<String, Func<Integer, String>> d9 = newDInt();
- System.out.println(
- format(newDCon(newDCon(newDCon(newDCon(newDCon(d4, d5), d6), d7), d8), d9))
- .apply(1).apply(2).apply(3)
- );
- //System.out.println(
- // format(newDCon(newDCon(newDCon(newDCon(newDCon(d4, d5), d6), d7), d8), d9))
- // .apply('a').apply('b').apply('c')
- //); //Integer以外の型はコンパイルエラー
- }
- }