OCaml, Concurrent Clean, Java: 型からプログラムを生成する

http://itpro.nikkeibp.co.jp/article/COLUMN/20071005/283903/
む。
Genericsの定義の仕方に似てるなー。

      • -

とりあえず、脊髄反射でCleanとJavaに翻訳
Java版はやや無理があるけど、一応ちゃんと動きます。出力形式をOCaml形式にしてますけど、Java式に出力することもできるはず。

Clean版

module Main

import Misc, List, String, StringCast

:: T a = {val2str :: [String] a -> String
         ,str2val :: [String] String -> a
         }

dup ls = (skip ls, skip (tail ls))
  where skip [a,b:c] = [a: skip c]

getSym = map (\i = "x" + toString i) [1..]

z =: {val2str = \sym v = v
     ,str2val = \sym s = s
     }

(^->) infixr 9 :: (T a) (T b) -> T (a -> b)
(^->) t1 t2 = {val2str = val2str, str2val = str2val}
  where
  val2str [x:sym] f = "(\\" + x + " = " + body + ")"
    where (sym1,sym2) = dup sym
          body = t2.val2str sym2 $ f $ t1.str2val sym1 x
  str2val sym s x = t2.str2val sym2 $ s + " " + (t1.val2str sym1 x)
    where (sym1,sym2) = dup sym

(*^) infixl 9 :: (T a) (T b) -> T (a,b)
(*^) t1 t2 = {val2str = val2str, str2val = str2val}
  where
  val2str sym (v1,v2) = "(" + s1 + "," + s2 + ")"
    where (sym1,sym2) = dup sym
          s1 = t1.val2str sym1 v1
          s2 = t2.val2str sym2 v2
  str2val sym s = (v1,v2)
    where (sym1,sym2) = dup sym
          v1 = t1.str2val sym1 ("fst " + s)
          v2 = t2.str2val sym2 ("snd " + s)

Start = t.val2str getSym f
  where
  t = z ^-> z ^-> z
  f a b = a

Java

public class Main {
  static int ct = 0;
  static String genSym () { return "x" + (++ct);}

  static interface Fun<Y,X>
   { X $ (Y y);}

  static interface T<A>
   { String val2str (A a);
     A str2val (String s);
   }

  static T<String> z = new T<String> ()
   { public String val2str (String a) { return a;}
     public String str2val (String a) { return a;}
   };

  static <A,B> T<Fun<A,B>> fun (final T<A> t1, final T<B> t2)
   { return new T<Fun<A,B>> ()
     { public String val2str (Fun<A,B> f)
        { String x = genSym ();
          String body = t2.val2str( f.$ (t1.str2val (x)));
          return "(fun " + x + " -> " + body + ")";
        }
       public Fun<A,B> str2val (final String s)
        { return new Fun<A,B> (){
            public B $ (A x) { return t2.str2val (s + " " + t1.val2str(x));}
          };
        }
     };
   }

  public static void main (String[] args)
   { Fun<String,Fun<String,String>> f = f();
     String s = fun(z,fun(z,z)).val2str(f);
     System.out.println(s);
   }

  static <A,B> Fun<A,Fun<B,A>> f ()
   { return new Fun<A,Fun<B,A>> ()
      { public Fun<B,A> $ (final A a)
         { return new Fun<B,A> ()
            { public A $ (B b)
               { return a;}
            };
         }
      };
   }
}