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?