Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

What do Promises/Futures/Async/etc. have to do with monads? Are monads a good abstraction to model those things?


Continuations / Promises / Futures form a Monad (https://www.stackage.org/haddock/lts-9.1/transformers-0.5.2....)

A Monad is any data structure with the follwing two methods:

    (>>=) :: m a -> ( a -> m b) -> m b
    pure :: a -> m a

the monadic bind is exactly `andThen` in javascript:

    (>>=) :: m a -> (a -> m b) -> m b
    (>>=) :: Future a -> (a -> Future b) -> Future b
    Future.andThen :: Future a -> (a -> Future b) -> Future b

and the monadic `pure` is exactly the `Future` constructor:

    pure :: a -> m a
    pure :: a -> Future a
    Future.always :: a -> Future a

Every Monad is a Functor, so you also get this one for free:

    map :: (a  -> b ) -> m a -> m b
    -- if I know how to convert a's to b's I can convert a future a to a future b
    Future.map :: (a -> b) -> Future a -> Future b

So basically, saying "futures are a monad" gives you all the useful functions that you would expect from a future based API, which is nice. It means you can use all kinds of higher level functions not specific to futures to abstract behaviour:

Like, given a list of element,s and a way to create a future for each element, create a future that returns a list of elements:

    forM :: (Monad m) => Array a -> (a -> m b) -> m (Array b
    Future.forEvery :: Array a -> (a -> Future b) -> Future (Array b)


Noted down, thanks for that. Will be handy for future whiteboard interview questions.


How do you begin to even read that notation stuff? Do you know of any resources for learning it?


The notation in the GP is Haskell-ish type notation, which is certainly different to the majority of languages out there today, but it's actually fairly simple (difficult to learn, but simple).

Quick glossary:

    ::      Defines a new function signature. The left hand side is the function name, and the right hand side is the signature.
    a -> b  A function which converts something of type a to type b
    m a     A generic m of type a. In Java/C# this might be written as m<a>. eg, `Array String` means an array of string elements, and might be written in C# as Array<String>.
Types starting with a lowercase letter (m, a, b) generally mean the type is generic - as in the function will take any type.

It might be helpful to define a function you already know:

    string_to_int :: String -> Int
Or, for changing an Array of something to an Array of something else:

   map :: (a -> b) -> Array a -> Array b
Here, we're defining a function that:

   1. Takes a function that converts an 'a' to a 'b' (a -> b)
   2. Takes an array of 'a'
   3. Returns an array of 'b'
Notice that 'a' and 'b' can be anything! Since the first parameter* is a function that handles the conversion from a to b, the map function actually doesn't need to know what type a and b are.

Let's say we pass in the `string_to_int` as the first parameter, now the type checker will actually infer the following function type:

    map :: (String -> Int) -> Array String -> Array Int
* Haskell functions actually only ever have one parameter, it uses Currying to accept multiple arguments: https://en.wikipedia.org/wiki/Currying


That's the Haskell language. There are a lot of "big" concepts in the language itself, compared to just about any other language from the last 50 years that people get paid to write, but the notation isn't hard to straighten out after a few tries. There's a really good intro here: http://learnyouahaskell.com/


They are just a way to wrap up the code/data somewhat similar to how callbacks are used in Javascript async code. And from using Haskell I believe they are an excellent abstraction when doing any async programming, once you wrap your head around them.

Although in terms of concurrency I've found Elixir/Erlang actor-esque process based system with messaging much more intuitive when building complex programs and much simpler to reason about than the various solutions Haskell offered. But I'm also not an expert at Haskell so take that comparison with a grain of salt.


Many of the actual implementations of these types are not actually monads by the monad laws, but they are monad-like in that they are containers for execution that can be composed with each other.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: