News for hackers. Stuff that matters.
Re:Escaping Hell with Monads (2017) by bjterry on Friday February 23, 2018 @10:43AM (#16446949)
People would use something like an Either monad in that case (in real code they may use an Error monad). If all your getData functions have a return type `Either MyError GoodResult` then you could write something like:

  data MyError = MyFirstError | MySecondError

  type GoodResult = String

  myFunc = 
    case doEither of
      Right x -> *handle good result*
      Left MyFirstError -> *handle error*
      Left MySecondError -> *handle error*
    where 
      doEither = do
        a <- getData
        b <- getMoreData a
        c <- getMoreData b
        d <- getEvenMoreData a c
        return d
If one of those functions returns a "Left" (or error) value, the remaining functions are not evaluated. If they all return a "Right" value, doEither evaluates to a successful "Right" value.

This works much better when all of your functions fail in the same way. If some functions fail with an empty Maybe and some fail with an Either and some with Error you will have to wrap all of those to take advantage of do-notation.

Re:Escaping Hell with Monads (2017) by dllthomas on Friday February 23, 2018 @10:58AM (#16447088)
> If some functions fail with an empty Maybe and some fail with an Either and some with Error you will have to wrap all of those

While this is true, the wrapping can be quite simple. Turning a Maybe into an Either is just a `fromMaybe (Left MyErr) Right`, and you can of course give it a name to clean it up even more.

Re:Escaping Hell with Monads (2017) by hota_mazi on Friday February 23, 2018 @12:02PM (#16447566)
That particular function is tied to Maybe and Either. Good luck with that when your functions start returning all types of different monads and welcome to monad transformer hell.
Re:Escaping Hell with Monads (2017) by dllthomas on Friday February 23, 2018 @12:44PM (#16447894)
Maybe and Either was the topic of discussion. If you want to discuss a different example, present a different example.

Attempting to speak usefully to vague generality... if your functions are returning different concrete monadic values you need to either run them and get something pure out or translate them into your current context. It's usually better practice, however, to leave the choice of monad up to the call site and only ask for the interfaces you need (MonadState, MonadReader, etc), at which point there's no call-site-local translation needed at all, you just have to make sure you're supporting the interfaces requested.

Re:Escaping Hell with Monads (2017) by hota_mazi on Friday February 23, 2018 @12:04PM (#16447576)
Please don't use Either to carry errors, it's really silly to use a language with a strong type system and then rely on convention to represent the error on the correct side of the monad.

Is error left or right again?

That's right, you shouldn't have to remember.

Use a more specific type for this, some GADT with clearly named instances (e.g. "Error" and "Value").

Re:Escaping Hell with Monads (2017) by dllthomas on Friday February 23, 2018 @06:43PM (#16450608)
I agree that would be a good convention to move away from - I don't think it takes a GADT, though; a regular data type should be fine.

For my part I think we should also deprecate the Functor (and dependent) instances for Either and tuple - but I know there are some who strongly disagree and I don't care all that much.

Re:Escaping Hell with Monads (2017) by nemetroid on Friday February 23, 2018 @12:31PM (#16447776)
Right is the right result and Left is the wrong result. That's about as easy it gets when it comes to remembering things. There is already a strong convention for using Either for this purpose and it's built into the standard library, since the Monad instance is designed to allow you to do this.

If you create your own data type for this, you are designing yourself into the Monad transformer hell you mention in another comment.

Re:Escaping Hell with Monads (2017) by hota_mazi on Friday February 23, 2018 @12:52PM (#16447945)
> That's about as easy it gets when it comes to remembering things

I use a statically typed language so I have fewer things to remember because the compiler does the bookkeeping for me.

`Either` is a generic variant record, it should not be used to carry errors.

And as a general rule, any programming construct that relies on convention instead of static typing is prone to generating bugs.

Re:Escaping Hell with Monads (2017) by nemetroid on Tuesday February 27, 2018 @11:50AM (#16475230)
> `Either` is a generic variant record, it should not be used to carry errors.

The name suggests that, but the Monad instance suggests that Either is an asymmetric data type, where the left and right branches carry different meaning.

> And as a general rule, any programming construct that relies on convention instead of static typing is prone to generating bugs.

If the Either branches were named `Error` and `Success`, using `Error` to carry errors would be just as much of a convention as using `Left` for that purpose (a more sensible convention, but nonetheless a convention). The only way you'd get around that is if you'd somehow encode in the language what is and what isn't an error and use that to statically force correct branch usage.

Re:Escaping Hell with Monads (2017) by taeric on Friday February 23, 2018 @04:30PM (#16449798)
To be fair, this is more relying on a pun than it is convention.

I don't think this changes your point, though.