I wrote the following Haskell code using do-nation.
And I'd like to convert it to Scala code
main :: IO ()
main = do
  print $ func1 (Right  1) (Right 2)
  print $ func1 (Right 10) (Right 3)
func1 :: Either String Int -> Either String Int -> Either String Double
func1 e1 e2 = do
  v1 <- e1
  v2 <- e2
  if v1 < v2
    then Right 1.515151  -- No meaning
    else Left  "some error"
Here is output of Haskell
Right 1.515151
Left "some error"
I wrote Scala code like the following. But I feel weird when I look at result <- if(v1 < v2)... and yield result.
object Main {
  def main(args: Array[String]): Unit = {
    println(func1(Right(1))(Right(2)))
    println(func1(Right(10))(Right(3)))
  }
  def func1(e1: Either[String, Int])(e2: Either[String, Int]): Either[String, Double] =
    for{
      v1 <- e1
      v2 <- e2
      // Weird...
      result <- if(v1 < v2)
                  Right(1.515151)
                else
                  Left("some error")
    } yield result
}
Here is output of Scala
Right(1.515151)
Left(some error)
I'd like to write bellow. But Scala doesn't allow me to write.
  // Invalid Scala Code
  def func1(e1: Either[String, Int])(e2: Either[String, Int]): Either[String, Double] =
    for{
      v1 <- e1
      v2 <- e2
    } {
      if(v1 < v2)
          Right(1.515151)
        else
          Left("some error")
    }
Could you tell me your idea for writing in beautiful way?
It can be prettified some.
for {
  v1  <- e1
  v2  <- e2
  res <- Either.cond(v1 < v2, 1.515151, "some error")
} yield res
It would be nice to just throw in a guard condition but, according to the Scala docs, that's not supported because Either has no withFilter method.
(Disclaimer: I don't know Haskell, so I may be wrong with this)
The difference between Haskell's do notation, and Scala's for/yield comprehension is that do sequence ends with a bind (i.e. flatMap), but for/yield ends with a normal map.
So in Haskell if you have a pure value in the last step, you have to wrap it in return, but in Scala you can yield it directly. yield is a keyword, not a function like Haskell's return. On the other hand, when in the last step you have a monadic value, in Haskell you can just put it there, but in Scala you have to add a step with result <- monadicValue and then yield result. 
This is just a difference in design in those two languages, and I believe you just have to get used to how Scala does this.
As for your question in the comment to the other answer:
In scalaz instead of Either.cond(p, a, b) you can use p.either(a).or(b), which returns a disjunction:
scala> import scalaz._, Scalaz._
scala> true.either(10).or("error")
res0: scalaz.\/[String,Int] = \/-(10)
Then you can wrap this disjunction in the monad you want, and then in EitherT. For example:
scala> EitherT(true.either(10).or("error").some)
res1: scalaz.EitherT[Option,String,Int] = EitherT(Some(\/-(10)))
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With