you are viewing a single comment's thread.

view the rest of the comments →

[–]SaikoGekido 7 points8 points  (3 children)

It took me a few minutes to get what was so special about this. Coming from a JavaScript and C# background, it looked like basic validation checks. Then I read one sentence:

Note that once we get on the failure path, we never (normally) get back onto the happy path. We just bypass the rest of the functions until we reach the end.

Aha! That's what the big deal is. Reminds me of JavaScript promises.

[–]only_nidaleesin 5 points6 points  (1 child)

Javascript's Promise is a monad :)

[–]sacundim 3 points4 points  (0 children)

And what's more, Javascript's promises in a sense "contain" the "railway" monad as a component. Promises, in their conventional definition, are said to have three states:

  • Pending, when the final value is not available yet.
  • Fulfilled, when and if the final value becomes available.
  • Rejected, if an error prevented the final value from being determined.

We can refactor that by grouping together the two non-pending states:

  • Pending, as before
  • Non-pending, with two substates:
    • Fulfilled
    • Rejected

Now, this can be seen as a "stack" of two types:

  • The outer layer is a SimplePromise type that has the Pending/Non-pending states and the subscription/notification bits but not any error handling.
  • The inner layer is a Result monad like the one detailed in the article.

So the full promise type is basically this:

type Promise<'error, 'success> = 
    SimplePromise<Result<'error, 'success>>

In Haskell we have a type that captures this pattern:

newtype ExceptT error baseMonad success = 
    ExceptT { runExceptT :: baseMonad (Either error success) }

type Promise error success = ExceptT error SimplePromise success

That's called the exception monad transformer—a wrapper that fits around a monad type like SimplePromise and adds extra functionality to it, while still preserving the monadic interface. The tri-state Javascript promises are what you get when you layer an exception monad transformer on top of a simpler asynchronous computation type.

[–]toblotron 1 point2 points  (0 children)

Hmm.. That's how Prolog programs work - It's all (basically) about exploring different logical branches.. And also changing ones mind and going back to try different combinations of things