为什么 Future 被认为是“引用不透明”?

Ami*_*Mal 4 monads functional-programming scala

我当时正在读《Scala with Cats》一书,其中有这样一句话,我将在这里引用:

\n
\n

请注意,Scala\xe2\x80\x99s Futures 是纯函数式编程的一个很好的例子,因为它们是引用透明的。

\n
\n

另外,还提供了一个示例,如下所示:

\n
val future1 = {\n  // Initialize Random with a fixed seed:\n  val r = new Random(0L)\n  // nextInt has the side-effect of moving to\n  // the next random number in the sequence:\n  val x = Future(r.nextInt)\n  for {\n    a <- x\n    b <- x\n  } yield (a, b)\n}\nval future2 = {\n  val r = new Random(0L)\n  for {\n    a <- Future(r.nextInt)\n    b <- Future(r.nextInt)\n  } yield (a, b)\n}\nval result1 = Await.result(future1, 1.second)\n// result1: (Int, Int) = (-1155484576, -1155484576)\nval result2 = Await.result(future2, 1.second)\n// result2: (Int, Int) = (-1155484576, -723955400)\n
Run Code Online (Sandbox Code Playgroud)\n

r.nextInt我的意思是,我认为这是因为从来没有引用透明的事实,对吧?因为identity(r.nextInt)永远不会等于identity(r.nextInt),这是否意味着identity也不是引用透明的?(或 Identity monad,以便与 Future 进行更好的比较)。如果计算的表达式是 RT,那么 也Future将是 RT:

\n
def foo(): Int = 42\n\nval x = Future(foo())\n\nAwait.result(x, ...) == Await.result(Future(foo()), ...) // true\n
Run Code Online (Sandbox Code Playgroud)\n

据我所知,几乎每个函数和 Monad 类型都应该是非 RT 的。或者说有什么特别的地方Future吗?我也阅读了这个问题及其答案,但找不到我要找的东西。

\n

Lui*_*rez 6

你实际上是对的,你正在触及 FP 最挑剔的点之一;至少在Scala中是这样。

从技术上讲,Future它本身就是RT。重要的是,与IO它不同的是,它不能将非 RT 的东西包装到 RT 描述中。但是,您可以对许多其他类型说同样的话,例如List, 或Option; 那么为什么人们不对此大惊小怪呢?
嗯,就像许多事情一样,细节决定成败。

List与or相反OptionFuture通常与非 RT 事物一起使用;例如 HTTP 请求或数据库查询。因此,人们强调Future在这些情况下不能保证 RT。更重要的是,在代码库中
引入并发性(不要与并行性混淆)只有一个原因;否则,它将与 相同。因此,控制执行的时间和方式通常很重要。 这就是为什么建议在所有用例中使用FutureTry
IOFuture

注意:您可以找到关于此cats PR的类似讨论及其链接讨论: https: //github.com/typelevel/cats/pull/4182