パラメータをバリデーションするのにfor を使うのがイディオムなのかなー。
case class Person(val name:String)
object Hello {
def validate(p:Person):Either[String,Boolean] =
for {
_ <- checkNotNull(p).right
v <- checkNotNullAndEmpty(p.name).right
} yield v
def checkNotNull[A](a:A):Either[String,Boolean] = if (a==null) Left("is null") else Right(true)
def checkNotNullAndEmpty[A](s:String):Either[String,Boolean] = {
if (s==null) Left("is null")
else if (s=="") Left("is empty")
else Right(true)
}
def main(args:Array[String]) = {
val p0 = new Person("taro")
val p1 = null
val p2 = new Person(null)
val p3 = new Person("")
val list = for ( p <- List(p0,p1,p2,p3)) yield (p, validate(p))
println(list)
}
}
└─[0] sbt run
[info] Set current project to validation (in build file:/Users/iwag/Devel/sandbox/scala/validation/)
[info] Running Hello
List((Person(taro),Right(true)), (null,Left(is null)), (Person(null),Left(is null)), (Person(),Left(is empty)))
[success] Total time: 1 s, completed 2014/04/20 17:06:23
どうでもいいけど、for () と for {} の違いなんだっけって思ったら、()ないだと区切りは;、{}だと改行。
元ネタ。
http://stackoverflow.com/questions/21351391/how-to-accumulate-errors-in-either-in-scala
http://stackoverflow.com/questions/12307965/method-parameters-validation-in-scala-with-for-comprehension-and-monads
元のstackoverflowは検出したエラーをaccumulateしたいとかだけど。