using tensor product in scala
May. 30th, 2014 06:35 amI just tried this code:
Why is this important?
See, if I have a class
This is better than having
because in the second case if username is bad, we will never know if prize is bad too; this way we detect only one error. Not so good for fast development. It's like what ancient compilers did.
Questions?
sealed trait Result[+T] { ... def <*>[U](other: Result[U]): Result[(T,U)] ... } case class Good[T](value:T) extends Result[T] { ... def <*>[U](other: Result[U]): Result[(T, U)] = other.flatMap(u => Good((value, u))) ... } case class Bad[T](errors:Traversable...) extends Result[T] { ... def <*>[U](other: Result[U]): Result[(T, U)] = Bad(errors ++ other.errors) ... } scala> val op = Good((1,"one")) op: Good[(Int, String)] = Good((1,one)) scala> for ((i,s) <- op) println(s"i=$i, s=$s") i=1, s=one
Why is this important?
See, if I have a class
Result[T]
, and it is applicative, so Result[T] <*> Result[U]
produces Result[(T,U)]
, I want to use the result, naming individual fields. Like in val username: Result[String] = getUserNameFromTheCloud(userId) val prize: Result[Prize] = rollTheDice val letter:Result[(String, Prize)] = for ((u, p) <- username <*> prize) yield congratulate(u, p) // etc
This is better than having
for(u <- username; p <- prize) yield congratulate(u,p)
because in the second case if username is bad, we will never know if prize is bad too; this way we detect only one error. Not so good for fast development. It's like what ancient compilers did.
Questions?