在scalaz中违反了Future monad的左恒等定律



假设我为Future:定义了一个Monad类型类的实例

val futureMonad = new Monad[Future] {
  override def point[A](a: ⇒ A): Future[A] =
    Future(a)
  override def bind[A, B](fa: Future[A])(f: A => Future[B]): Future[B] =
    fa flatMap f
}

严格地说,这不是monad,因为它违反了左身份定律:

futureMonad.point(a) bind f == f(a)

如果f抛出异常,则左侧表达式的结果将是失败的Future,而右侧当然会抛出异常。

但这种违规行为的实际含义是什么?一个系统在哪些方面会因为这种"不当行为"而失败?

TryFuture这样的monad用一个monad定律换另一个定律,这在它们应该使用的上下文中更有用:由(TryFuture)、flatMap、map组成的表达式永远不会引发非致命异常。这就是"防弹"原则。因此,实际上这种方法确实可以保护您免受许多失败的影响,并且左单位定律是故意失败的。

这只是意味着,就理解而言,以下重构不是语义保留的:

for (fut <- Future(a); x <- f(fut)) yield x  ==>  f(a)

但实际上,这只是书写左派身份法的另一种方式。

进一步解释无效重构:

for (fut <- Future(a); x <- f(fut)) yield x
==>  for (x <- f(a)) yield x  // by left identity law: WRONG, because left identity law does not hold
==>  f(a)                     // by 1st functor law:   WRONG, because previous line was wrong

最新更新