我可以使用Monads表示非顺序/并行执行吗?

时间:2017-10-17 12:09:57

标签: scala haskell monads applicative

所以我终于理解为什么Applicative对于表示并行执行非常有用,而Monads对于表示顺序执行非常有用。

话虽如此,我也明白Monads比Applicative更强大,所以我可以用ap函数来表示bind函数吗?

换句话说......我可以用Monads表示并行执行吗?

3 个答案:

答案 0 :(得分:2)

The Monad laws有话要说:

  

此外,Monad和Applicative操作应该相关   如下:

pure = return
(<*>) = ap

鉴于ap defined按顺序组成计算,

ap mf mx = do
    f <- mf
    x <- mx
    return (f x)

只有一种方法可以阅读该法则:暴露monadic接口的类型不能使用Applicative进行并行计算。您可以为monad提供newtype包装器,该包装器具有并行Applicative实例和 no Monad实例,但您不能同时执行这两个操作

理论上,理论和实践是相同的,但在实践中,它们不是。在现实世界中,你确实看到人们弯曲这些规则并解释上述法则意味着(<*>)应该道德等同于ap,即使它不是完全等同于

我知道的最好的例子恰好是直接解决你问题的那个例子。 Haxl是一个为并发IO实现特定于域的语言的库。 GenHaxl monad <*>会在可能的情况下自动并行两个计算,而>>=按顺序运行它们(因为它必须)。这明显违背了法律的规定,但是由于Haxl用于数据库读取,它不会改变任何东西(而不是,这样做)你有点可以逃脱它,世界不会爆炸。

答案 1 :(得分:1)

您可以<*>ap实施Functor,也可以Monad

class Functor m => Monad m where
  join :: m (m a) -> m a
  return :: a -> m a

(>>=) :: Monad m => m a -> (a -> m b) -> m b
m >>= f = join $ fmap f m

(<*>) :: Monad m => m (a -> b) -> m a -> m b
fs <*> xs = fs >>= \f -> xs >>= \x -> return (f x)

ap :: Monad m => m (a -> b) -> m a -> m b
ap = (<*>)

此示例隐藏了Haskell的标准Monad定义,而是根据Monadjoin定义return,但您也可以定义{{1}来自join;两种方式都有效。

答案 2 :(得分:0)

考虑一个案例:假设我们有两个期货。

jQuery_3_2_1("input[id^=DepartureDay]").on("change", function() {
  alert("dd");
});

在上面的例子中,val future1 = Future { //some long running computation 1 } val future2 = Future { // some othe long running computation 2 } future1.flatMap(_ => future2) future1并行运行,只要执行池中有足够的线程。

我们能够并行运行期货。那么,这是什么意思?

当前一个任务和当前任务(monad)之间存在数据依赖时,Monads会出现。但是,如果它们可以并行运行(至少在未来的情况下),则没有数据依赖性。

现在考虑一个案例:

future2

现在一个未来在其他人完成后运行。由于数据依赖性,现在执行必须是串行的。第二个未来取决于第一个未来的价值。