関数
Scala の関数
Scala の関数はファーストクラス。
変数に代入したり、他の関数の引数に渡したり出来る。
val inc = (i: Int) => i + 1
val cl: String => Int => String =
(msg: String) => (rep: Int) => msg * rep
Scala では、変数/定数定義で型パラメータをとるような値は定義出来ない。メソッ
ド定義で代用するので、便宜上def を用いた定義も関数と呼ぶこととする。
def show[A]: A => String = (a: A) => a.toString
9 / 59
関数
Scala の関数
関数を引数にとったり、返り値として返したりする関数を高階関数と呼ぶ。
val calc: (Int => Int => Int) => Int => Int => Int =
(f: Int => Int => Int) => (i: Int) => (j: Int) => f(i)(j)
val add: Int => Int => Int =
(i: Int) => (j: Int) => i + j
val multi: Int => Int => Int =
(i: Int) => (j: Int) => i * j
scala> calc(add)(1)(2)
res15: Int = 3
scala> calc(multi)(1)(2)
res16: Int = 2
10 / 59
あれもこれも型クラス
for 式再説
Scala のfor 式は糖衣構文。
val fooOpt: Option[Int] = ...
val barOpt: Option[Int] = ...
for {
foo <- fooOpt
bar <- barOpt
} yield foo + bar
以下のように展開される。
fooOpt.flatMap(foo =>
barOpt.map(bar =>
foo + bar
)
)
45 / 59
あれもこれも型クラス
for 式再説
for 式の展開には他にもルールがある。compiler の型付け前に展開されるので、
必ず全ての展開対象メソッドを実装している必要はない。
abstract class C[A] {
def map[B](f: A => B): C[B]
def flatMap[B](f: A => C[B]): C[B]
def withFilter([: A => Boolean): C[A]
def foreach(b: A => Unit): Unit
}
46 / 59
あれもこれも型クラス
「for 式が使える」型クラス
便宜上map, flatMap のみを考える。
trait CanWriteForSyntax[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
例えば、Option のインスタンスは以下の通り。
implicit val optionCanWriteForSyntax: CanWriteForSyntax[Option] =
new CanWriteForSyntax[Option] {
def map[A, B](fa: Option[A])(f: A => B): Option[B] =
fa.map(f)
def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] =
fa.flatMap(f)
}
47 / 59