In general they are both syntax sugar for monadic bind/flatMap and fmap/map functions, so they should be equivalent in expressiveness.
The last example you posted wouldn’t work in either language. Keep in mind that
return in Haskell has nothing to do with
return in imperative languages like Python/Java, etc… In particular you cannot use it as a statement to return early from a computation.
return is an alias for
pure, which takes a value and lifts it into the monad you’re using. So if the do-notation is used with
return will lift
Maybe, so it evaluates to
The very first example you posted has redundant usage of
You’d normally write it like this (and probably replace
pure, which is the same but a clearer name):
fun :: Maybe Int
if 1 > 0 then
Using a conditional in for-comprehensions isn’t any different from using one anywhere else in Scala. You just have to follow the types and understand that if-else is an expression, not a statement.
def calc1(): Option[Int]
def calc2(): Option[Int]
def calc3(): Option[Int]
intA <- calc1()
intB <- if (intA > 0) calc2() else calc3()
} yield intA + intB
Note that the if-else-expression has type Option[Int], so we unwrap it the same way we did with the result of calc1().
edit: The Haskell do-notation is confusing for beginners because the last expression needs to have the same type as the Monad it operates on. But the often needed lifting into the Monad isn’t automatic, so people use
return to do this. But
return is just an alias for
pure and confuses people coming from imperative languages, where
return has special meaning.
Learn You A Haskell introduces the do-notation without
pure and uses the specific constructor of the Monad (for
Maybe this is
Just). Imo that’s the best way to go about it:
foo :: Maybe String
foo = do
x <- Just 3
y <- Just "!"
Just (show x ++ y)