kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

Scalaでランクn多相をエミュレート

ヒビルテ(2008-05-29)より:

OCamlの場合

一方、OCamlの場合にはランクN多相に直接対応してはいない*2けど、レコードのフィールドが多相型を持つことが出来るので、多相関数をレコードに包んで受け渡すことでエンコードできる。

type some_record = {x:int list;y:float list}

type op = { app : 'a. 'a list -> 'a list -> 'a list }

let lift f {x=x1;y=y1} {x=x2;y=y2} =
  {x=f.app x1 x2;
   y=f.app y1 y2}

let append' = lift { app = (@) }
http://www.tom.sfc.keio.ac.jp/~sakai/d/?date=20080529#p01

あんまり自信が無いけど、Scalaに翻訳してみると、次のような感じかな。
Scalaにはレコード型は無いので、structural typeを使ってエミュレート
してみた。

import Function._
type someRecord = { val x :List[Int]; val y :List[Float] }
type op = { def app[A] :List[A] => List[A] => List[A] }
def lift(f :op)(p1 :someRecord)(p2 :someRecord) = new {
  val x = f.app(p1.x)(p2.x)
  val y = f.app(p1.y)(p2.y)
}
val append = lift(
  new { def app[A] = curried((_:List[A]).++[A](_:List[A])) }
) _
val result = 
  append(
    new { val x = List(1); val y = List(1.5f) }
  )(new { val x = List(2); val y = List(2.5f) })
println(result.x, result.y) //(List(1, 2),List(1.5, 2.5))