Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gakuzzzz/8fba6eb005856265005c to your computer and use it in GitHub Desktop.
Save gakuzzzz/8fba6eb005856265005c to your computer and use it in GitHub Desktop.
Scalaでランク2多相がほげほげ という話

Haskell での forall の例

Haskellのforallについて理解したことを書いておく(ランクN多相限定)。 より拝借

-- コンパイル通らない
func:: ([a] -> Int) -> Int
func f = f [1, 2, 3] + f["a", "b", "c"]

-- コンパイル通る
func:: (forall a. [a] -> Int) -> Int
func f = f [1, 2, 3] + f["a", "b", "c"]

Scala でやってみる

// コンパイル通る
def func(f: Seq[Any] => Int): Int = {
  f(List(1, 2, 3)) + f(List("a", "b", "c"))
}
func(_.size)
// この例だと共変あるしAny型あるしでScalaではランク2多相無くても書けちゃう
// コンパイル通る
import scala.collection.mutable
def func(f: mutable.Seq[Any] => Int): Int = {
  f(mutable.ListBuffer(1, 2, 3)) + f(mutable.ListBuffer("a", "b", "c"))
}
func(_.size)
// 非変にしてみるけど、ぜんぶSeq[Any]として扱えるのでやっぱ書けちゃう
// コンパイル通らない
def func[A](f: Seq[A] => Int): Int = {
  f(List(1, 2, 3)) + f(List("a", "b", "c"))
}
// 無理やりHaskellの例に合わせて見る
// コンパイル通る
trait SeqConsumer {
  def apply[A](seq: Seq[A]): Int
}
def func(f: SeqConsumer): Int = {
  f(List(1, 2, 3)) + f(List("a", "b", "c"))
}
func(new SeqConsumer { def apply[A](seq: Seq[A]): Int = seq.size })
// trait でランク2を表現してみる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment