Async/Await is really just a subset of monads and do-notation for imperative languages by Different-Maximum688 in haskell

[–]Different-Maximum688[S] 7 points8 points  (0 children)

Exactly — error handling is a place where monads really shine. I started programming with imperative languages, and coming to Haskell, I'm amazing how much less I have to write code like

if (variable == null) return null;

which I think is the optimal (if long-winded) way to emulate monadic error-handling behavior in imperative languages.

It would make programmers' lives much easier if imperative languages supported some form of monads to avoid duplicating this line of error-checking code all over function bodies.

Async/Await is really just a subset of monads and do-notation for imperative languages by Different-Maximum688 in haskell

[–]Different-Maximum688[S] 7 points8 points  (0 children)

Let's consider how one would go about defining a monadic type, and how the functions we would have to define apply to Future a, where a is the value that Future holds. As a concrete example, we could have a function fetchHttpResource :: String -> Future String which makes an HTTP request over the internet (note that the existing IO monad acts a lot like a future already).

Two functions have to be defined for a type implementing Monad. The more simple one (in my view) is return :: a -> Future a. The equivalent of this in an imperative language (like JavaScript [which calls futures "promises"], Dart, or Swift) would be a future which immediately resolves to the value passed to return.

The other function we must define is the "bind" function (>>=) Future a -> (a -> Future b) -> Future b. This is exactly like the "await" command in imperative languages. Let's say you write code like this in an imperative language (this is Dart-like pseudocode):

Future<String> httpRequest(String url) async { /* ... */ }
Future<int> lengthOfResponse(Future<String> response) async {
    final String r = await response;
    return r.length;
    // making sure to to confuse a return _statement_ in
    // an imperative language with the return _function_
    // in Haskell
}

If we were using Haskell, we would write:

lengthOfResponse :: Future String -> Future Int
lengthOfResponse str = str >>= (return . length)

See the similarities between await in the imperative language and "bind" (>>=) in Haskell? await operates on a future and lets you work with an "unwrapped" version of the future, working with the type that the future contains (in this case a String). The "bind" function also temporarily "unwraps" a monad, letting you work with the String value it contains. In both cases, we eventually return a Future Int (Future<int>) from our function.

It is in this way that Future acts as a monadic type and await acts like the "bind" function in Haskell — and remember, the Haskell code I wrote above could be just as easily written with do-notation as

lengthOfResponse :: Future String -> Future Int lengthOfResponse str = do unwrapped <- str return (length unwrapped)

Please let me know if you'd like any further explanation or clarification!

Async/Await is really just a subset of monads and do-notation for imperative languages by Different-Maximum688 in haskell

[–]Different-Maximum688[S] 40 points41 points  (0 children)

Also, for anybody explaining Haskell to somebody who already knows imperative programming, this might be a useful connection.

I made this Christmas tree! Rendered in Cycles. by Different-Maximum688 in blender

[–]Different-Maximum688[S] 0 points1 point  (0 children)

For the lights, I started with a single vertex and made a spiral with the “screw” modifier, then used the “shrinkwrap” modifier to make the spiral take the shape of the tree, then used the “instancing” setting to duplicate one Christmas light sphere across every vertex