Re:Rust and the Blub Paradox
by steveklabnik on Saturday January 23, 2016 @02:42PM
(#10959721)
The usual implementation of the Either/Option monads already does this though:
instance Monad Maybe where
return x = Just x
Nothing >>= f = Nothing
Just x >>= f = f x
fail _ = Nothing
and instance (Error e) => Monad (Either e) where
return x = Right x
Right x >>= f = f x
Left err >>= f = Left err
fail msg = Left (strMsg msg)
The end result is still a value of that type. You get the short-circuting behavior as soon as you hit Nothing/Left.It only short-circuits to the end of the do block. But once you leave the do block the error isn't propagated anymore.
Re:Rust and the Blub Paradox
by steveklabnik on Saturday January 23, 2016 @03:12PM
(#10959856)
Right. Maybe this is because I tend to write small functions, but the amount of things that end in `Ok(())` especially with IO still makes me think it would be useful.
Can't break be simulated by something like MaybeT? And forWithBreakM :: [a] -> (a -> m (Maybe b)) -> m [b] that stops when f yields Nothing? (isn't this actually sequence . forM?)
Yeah, there are transformations that we could apply to the code to make it work. But those transformations aren't trivial in the general case: how about breaking out of multiple loops or returns out of the function from inside loops? At some point, the transformations that we'd have to do would get so complex they'd hinder the programmer's mental model of what code will get generated. We'd also have to do a fair bit of work to make sure the optimizer can figure out what we're encoding so as to not lose performance.
This is why I called try! monads for imperative languages: the early return that is expands to is the key to playing nice with imperative constructs like break and continue.