Haskell-like な言語の実装

日曜日。晴。
寝坊。あっという間に午前が終わる。

NML で音楽を聴く。■バッハのブランデンブルク協奏曲第五番 BWV1050 で、指揮はラース・ウルリク・モルテンセン、コンチェルト・コペンハーゲンNMLCD)。ふつうによいな。■ジェルジ・クルターグの「遠方より III」、「遠方より V」、「ヤコブ・オブレヒトへのオマージュ」、「六つの楽興の時」 op.44、「アリオーソ - ヴァルター・レヴィンへのオマージュ 85」で、演奏はモリナーリ四重奏団(NMLCD)。やっぱり現代曲は聴かないとな。目が覚める。新鮮である。■ショスタコーヴィチのヴァイオリン協奏曲第一番 op.77 で、ヴァイオリンはボリス・ベルキン、指揮はウラディーミル・アシュケナージ、ロイヤル・フィルハーモニー管弦楽団NMLCD)。


Ruby で遅延評価の帰結として、Haskell-like な言語を(Ruby で)実装する結果になった。骨格は他の人の JavaScript のそれを借りたものであり、全然オリジナルでも何でもないが。しかし関数型言語の勉強になった。遅延評価、カリー化、部分適用、関数合成、無限リストなど、それっぽいことができますよ。例えばクイックソート

given = make_list([*1..5].shuffle)
evaluate Print + given

is_large = operator(:>)
is_not_large = operator(:<=)

quick_sort = Lambda1 {|list|
  xxs = evaluate(list)
  if xxs.instance_of?(Cons)
    x, xs = Car * xxs, Cdr * xxs
    left  = quick_sort + Select * (is_large * x) * xs
    right = quick_sort + Select * (is_not_large * x) * xs
    Concat + left + Concat * (Enlist * x) * right 
  else
    list
  end
}
evaluate Print + quick_sort * given

こんな風に実装できるのだ。まあ遅いのですけれどね。RubyDSL 用言語としての柔軟性がすごい。

フィボナッチ数列ならこんな感じ。

fib = Thunk {
  zero >> (one >> ZipWith + Add + fib + Tail * fib)
}
evaluate Print + Take * ten * fib
#=>[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]