我通過閱讀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]型別的值嗎?一般來說,我對粗體代碼中發生的事情感到困惑。這是一本非常好的書,所以我對目前的進展很滿意,我覺得我學到了很多關于函式式編程的知識。如果這個問題格式不正確并且格式有問題,我深表歉意。這是我關于堆疊溢位的第一篇文章!感謝那些看這個的人,我希望它可以幫助有同樣問題的人。
uj5u.com熱心網友回復:
方法 nonNegativeLessThan 的 if 陳述句如何過濾??掉大于 32 位整數中 n 的最大倍數的 i 值?
如果i大于 的最大倍數n,i (n - 1) - mod則將溢位并產生負數。然后>= 0是假的。
else 子句中的遞回呼叫不是回傳 Rand[Int] 型別的值嗎?
嗯,nonNegativeLessThan(n)確實是型別Rand[Int]。但是它說nonNegativeLessThan(n)(???),也就是說,它適用nonNegativeLessThan于n,然后它將結果值(型別Rand[Int],它是一個函式型別)應用于???,并產生一個Int。或者更確切地說,如果它產生了真正的價值,它就會這樣做,???但它沒有。
這里的問題是您必須傳遞 RNG 的狀態而不是???,但該map函式不允許您訪問該狀態。你需要flatMap解決這個問題——大概這就是本書接下來要討論的內容。
uj5u.com熱心網友回復:
想象一下,您有一個由一組整陣列成的新域,例如 0 到 11。Rand 型別表示該域中的一個亂數,但這種型別不能傾斜。這意味著不可能有比其他數字更有可能生成的數字。
如果要生成一個小于四的正數,可以使用 Rand 型別的map函式,它允許轉換狀態動作的結果。首先,它生成一個非負數并通過映射轉換結果,應用匿名函式: _ % n以獲得小于 n 的數。
def nonNegativeLessThan(n: Int): Rand[Int] =
map(nonNegativeInt) { _ % n }
它使用模運算:
scala> 1 % 4
res0: Int = 1
scala> 2 % 4
res1: Int = 2
scala> 3 % 4
res2: Int = 3
scala> 4 % 4
res3: Int = 0
scala> 5 % 4
res4: Int = 1
scala> 6 % 4
res5: Int = 2
scala> 7 % 4
res6: Int = 3
scala> 8 % 4
res7: Int = 0
scala> 9 % 4
res8: Int = 1
scala> 10 % 4
res9: Int = 2
可以看到,這個域中 4 的最大倍數是 8,所以如果生成的非負數是 9 或 10,我們就有問題了。具有 1 或 2 的概率大于具有 3 或 0 的概率。因此,另一個實作檢測到由于 nonnegativeInt 而首先生成的數字不大于 n in 的最大倍數一個特定的域,書中的 Int32 數字域,來擁有一個無偏生成器。
是的,那本書很棒。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/415353.html
標籤:
