scala - 如何使有状态 API 变得纯粹

标签 scala functional-programming

我通过阅读Scala 中的函数式编程(又名红皮书)这本书来学习函数式编程,并且我遇到了我的第一个真正的障碍。在第6章中,本书使用随机数生成器的示例来说明如何使用副作用来改变状态。然后,本书继续演示您通常会遇到的模式,以及在制作功能性有状态 api 时可能会采取的一些切线。当我试图理解以下代码时,我的问题出现了:

type Rand[+A] = RNG => (A, RNG)

def map[A, B](s: Rand[A])(f: A => B): Rand[B] =
  rng => {
      val (nxt, nxtrng) = s(rng)
      (f(nxt), nxtrng)
  }

def nonNegativeLessThan(n: Int): Rand[Int] =
  map(nonNegativeIntv2) { i =>
    val mod = i % n
    if (i + (n - 1) - mod >= 0) mod else nonNegativeLessThan(n)(???)
  }

我希望这是足够的上下文来了解代码的作用。这直接来自第 86 页的书。方法 nonNegativeLessThan 的 if 语句如何过滤​​掉大于 32 位整数中 n 的最大倍数的 i 值? else 子句中的递归调用不是返回Rand[Int] 类型的值吗?一般来说,我对粗体代码中发生的事情感到困惑。这是一本非常好的书,所以我对到目前为止的进展感到满意,并且我觉得我学到了很多关于函数式编程的知识。如果这个问题格式不正确并且格式存在问题,我深表歉意。这是我关于堆栈溢出的第一篇文章!感谢那些看到这篇文章的人,我希望它对遇到同样问题的人有所帮助。

最佳答案

How does the if statement for method nonNegativeLessThan filters out values of i that are greater than the largest multiple of n in a 32 bit integer?

如果i大于n的最大倍数,则i + (n - 1) - mod将溢出并产生负数。随后的 >= 0 则为 false。

Doesn't the recursive call in the else clause return a value of type Rand[Int]?

嗯,nonNegativeLessThan(n) 确实是 Rand[Int] 类型。然而它说的是 nonNegativeLessThan(n)(???),也就是说,它将 nonNegativeLessThan 应用于 n,然后应用结果值(类型为 Rand[Int],这是一种函数类型)到 ???,并生成一个 Int。或者更确切地说,如果 ??? 曾经产生过真正的值(value),它就会这样做,但事实并非如此。

这里的问题是您必须传递 RNG 的状态而不是 ???,但是 map 函数不允许您访问该状态。您需要 flatMap 来解决这个问题 - 这大概就是本书接下来要讨论的内容。

关于scala - 如何使有状态 API 变得纯粹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70644838/

相关文章:

scala - 如何从 TypeClass 解析中排除特定类型?

haskell - 如何为具有两个参数的类型实例 `Functor`?

java - Scala:如何使用 Java 回调 API

scala - 在出现一定数量的错误后停止在 Apache Spark 中处理大型文本文件

programming-languages - 测量单位是 F# 独有的吗?

functional-programming - Scheme中的树数据结构算法?

functional-programming - OCaml 懒惰评估 : 'a lazy_t vs unit -> ' a

functional-programming - SML:基本 Prime 测试

android - SBT Android-Plugin 中 "proguardInJars"的语义是什么?

scala - 在 Scala 中,是否可以使用 Plotly 的 Scatter3d?