Scalaでモナドを、なんとなくイメージするためのヒント
Scalaでモナドを説明する際には、まずリストを用いるのがイメージしやすい。
scala> List(2, 3, 5, 7, 11, 13, 17, 19).foreach(println) 2 3 5 ...
このListの値に効果を与えて、与えられたものを関数(ここではprintln
)でシーケンシャルに評価している。
次にScalaの代表的な型としてOption
があるが、これもモナドである。
Optionは値をもつ、持たないそれぞれを、Some
、None
という箱で表す。
scala> Option(10) res: Option[Int] = Some(10) scala> Option(null) res: Option[Null] = None
これに対して、リストと同じようにmap
や、filter
、foearch
などのメソッドを使うことができる。
scala> Option(10).foreach(println) 10 scala> Option(10).map(_ * 2).foreach(println) 20
また、例外処理が発生する場合に、このOptionをつくるための方法として、scala.util.Try
がある。
これによって、生成されるOption
に対して、リストと同様な処理をすることができる。
scala> import scala.util.Try import scala.util.Try // 例外が発生しないパターン scala> Try( "10".toInt ).toOption res: Option[Int] = Some(10) scala> Try( "10".toInt ).toOption.foreach(println) 10 // 例外が発生するパターン scala> Try( "fuga".toInt ).toOption res: Option[Int] = None scala> Try( "fuga".toInt ).toOption.foreach(println)
また、Optionと同様に、Futureもモナドとして扱うことができる。
Furute[Any]
に対して、やはりリストと同様に、map
やforeach
などを適用できる。
Future
の場合は、処理が行われた後に与えた関数を評価していく。
scala> import scala.concurrent._ scala> import ExecutionContext.Implicits.global scala> val f: Future[Int] = future { (1 to 100).foldLeft(0)((x: Int, y: Int) => x + y) } warning: there was one deprecation warning; re-run with -deprecation for details f: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@ca213f scala> f.foreach(println) 5050