现代化的Java(三十五)——Future Monad

今天在 Jaskell Dotty 里,增加了一个 monad instance:

given futureMonad (using ec:ExecutionContext): Monad[Future] with {
  def pure[A](x: A): Future[A] = Future.successful(x)

  extension[A, B] (x: Future[A]) {
    override def map(f: A => B): Future[B] = x.map(f)
    def flatMap(f: A => Future[B]): Future[B] = x.flatMap(f)
  }
}

这个 instance 使得 scala.concurrent.Future 也可以遵循我们在 jaskell 中定义的 monad 行为,包括 applicative 。例如下面这个测试代码:

class FutureSpec extends AsyncFlatSpec with Matchers {
  import jaskell.futureMonad
  
  val future = Future("success") *> Future(3.14)  {value => value * 2*2}  value should be (3.14 * 2 * 2)) 
  }
}

因为这段代码旨在测试 monad 功能,所以没有做很复杂的异步逻辑测试。future 对象在前后三个任务都成功的前提下,返回中间 Future(3.14) >> {value => value 2 * 2} 的求值结果。
当然,实际上 scala 本身就支持类似 haskell do 的 for yield,future 的定义完全可以写成:

for {
  _ <- Future("success") 
  result > {value => value * 2*2}
  _ <- Future("Right")
} yield result