4

I'm reading the doc of package async, and trying to find something similar to JavaScript's Promise, and I find Concurrently, which is the most close concept that implemented Functor, Applicative (Promise.all), Alternative (Promise.race). But it doesn't implement Monad (Promise.then), I'm wondering why.

I think it maybe because (>>=) is a sequential operation, which conflict with the name Concurrently, but is this the only reason? is there some more important reason here?

luochen1990
  • 3,689
  • 1
  • 22
  • 37
  • 1
    Yes, that is exactly the reason: the whole point of monads is that they encode _order of operations_, and `Concurrently` expresses parallelism, which is an inherently unordered thing. But `Concurrently` is not actually equivalent to JS promise. Promises don't give you parallelism, only asynchrony. Perhaps if you described what your ultimate goal is, people here could help you find the right solution. – Fyodor Soikin May 08 '19 at 03:03
  • 1
    Related GitHub issue: https://github.com/simonmar/async/pull/26 – danidiaz May 08 '19 at 17:56

1 Answers1

5

The Monad typeclass states that (<*>) and ap should be equivalent. (<*>) for Concurrently evaluates both the LHS and the RHS at the same time. ap can't evaluate the RHS until the LHS is done, since (>>=) needs to finish evaluating the LHS before it can call the function that gives it the RHS.

  • But why can't we just let `ap = (<*>)`, is there any constraints that ap must be implemented by `(>>=)` ? – luochen1990 May 08 '19 at 03:15
  • I have read the code just now, and find that maybe it is just a Historical issues? – luochen1990 May 08 '19 at 03:16
  • `ap` isn't in the `Monad` class. It's defined as `ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }`, for every Monad. And no, it's not a historical issue. – Joseph Sible-Reinstate Monica May 08 '19 at 03:17
  • So I'm wondering, why can't we design a monad, which Applicative is a concurrent version, and Monad is a sequential version? why `(<*>)` and `ap` must be equivalent? what is the motivation to add this rule? – luochen1990 May 08 '19 at 03:21
  • For your first 2 questions, because the Monad laws say so. For your third, lots of reasons. See https://www.reddit.com/r/haskell/comments/3v9qlf/why_must_ap/ and https://stackoverflow.com/q/46913472/7509065 and https://stackoverflow.com/q/24112786/7509065 for some of them. – Joseph Sible-Reinstate Monica May 08 '19 at 03:26
  • 3
    I think i got it. these laws like `pure = return` and `(<*>) = ap` makes a promise that the `Applicative` and `Monad` instance of some specific data have the same semantics. – luochen1990 May 08 '19 at 03:45
  • @luochen1990: exactly there are contracts between `Functor`, `Applicative` and `Monad`. One can not just implement these in an isolated manner, the `Functor` "partly determines" the "shape" of the `Monad`, and vice versa. – Willem Van Onsem May 08 '19 at 08:52
  • Thanks, I think maybe Haxl is what I want. – luochen1990 May 08 '19 at 10:03