Hacker News new | ask | show | jobs
by gemstones 1161 days ago
I think the commenter who mentioned syntax is on to something. If I write this

    fn my_big_subroutine(ma: Option<isize>, mb: Option<isize>) -> Option<bool> {
        match (ma, mb) {
            (Some(a), Some(b)) => Some(a > b),
            (_, _) => None,
        }
    }
it’s clearer to me what the intent is. I’m not sure why the other syntax is so hard for me but it feels hard to understand for some reason.
1 comments

The `do` block I showed is more like this:

    fn my_big_subroutine(ma: Option<isize>, mb: Option<isize>) -> Option<bool> {
        match (ma) {
            (Some(a)) => 
              match (mb) {
                (Some(b)) => Some(a > b),
                _ => None
              }
            (_) => None,
        }
    }
Which in this case is equivalent in this example, however I'm trying to stress the sequencing. Imagine `mb` had some very expensive computation in it, then it will remain an unevaluated thunk if we shortcircuit on `ma`.

> it’s clearer to me what the intent is. I’m not sure why the other syntax is so hard for me but it feels hard to understand for some reason.

We can write `myBigSubroutine` with case matching:

    case ma of
      Nothing -> Nothing
      Just a ->
        case mb of
          Nothing -> Nothing
          Just b -> Just (a > b)
In fact, the `do` notation version desugars to something equivalent to this snippet.

The motivation for using the `Monad` instance (and thus `do` notation), is that it allows us to be polymorphic over the effect described by `>>=` (and thus `do`).

This lets us have a customized version of sequencing computations specialized to whatever "effect" we need, not just casing on optional values.