- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图了解如何在 scala 中利用 monad 来解决简单的问题,以此来提高我的熟悉度。一个简单的问题是使用函数式随机数生成器来估算 PI。我在下面包含了一个简单的基于流的方法的代码。
我正在寻求帮助将其转化为单子(monad)方法。例如,是否有一种惯用的方法将此代码转换为以堆栈安全的方式使用状态(和其他 monad)?
trait RNG {
def nextInt: (Int, RNG)
def nextDouble: (Double, RNG)
}
case class Point(x: Double, y: Double) {
val isInCircle = (x * x + y * y) < 1.0
}
object RNG {
def nonNegativeInt(rng: RNG): (Int, RNG) = {
val (ni, rng2) = rng.nextInt
if (ni > 0) (ni, rng2)
else if (ni == Int.MinValue) (0, rng2)
else (ni + Int.MaxValue, rng2)
}
def double(rng: RNG): (Double, RNG) = {
val (ni, rng2) = nonNegativeInt(rng)
(ni.toDouble / Int.MaxValue, rng2)
}
case class Simple(seed: Long) extends RNG {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = Simple(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
def nextDouble: (Double, RNG) = {
val (n, nextRNG) = nextInt
double(nextRNG)
}
}
}
object PI {
import RNG._
def doubleStream(rng: Simple):Stream[Double] = rng.nextDouble match {
case (d:Double, next:Simple) => d #:: doubleStream(next)
}
def estimate(rng: Simple, iter: Int): Double = {
val doubles = doubleStream(rng).take(iter)
val inside = (doubles zip doubles.drop(3))
.map { case (a, b) => Point(a, b) }
.filter(p => p.isInCircle)
.size * 1.0
(inside / iter) * 4.0
}
}
// > PI.estimate(RNG.Simple(10), 100000)
// res1: Double = 3.14944
我怀疑我正在从猫的 Applicative
monad 中寻找类似 replicateM
的东西,但我不确定如何排列类型或如何做以一种不会在内存中累积中间结果的方式。或者,有没有一种方法可以通过 for
理解来迭代构建 Point
?
最佳答案
如果您想以堆栈安全的方式使用 monad 进行迭代,那么在 Monad
类型类中实现了一个 tailRecM
方法:
// assuming random generated [-1.0,1.0]
def calculatePi[F[_]](iterations: Int)
(random: => F[Double])
(implicit F: Monad[F]): F[Double] = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations): F[Either[Iterations, Double]] = for {
x <- random
y <- random
isInCircle = (x * x + y * y) < 1.0
newTotal = data.total + 1
newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
// iterates until Right value is returned
F.tailRecM(Iterations(0, 0))(step)
}
calculatePi(10000)(Future { Random.nextDouble }).onComplete(println)
它使用 by-name 参数,因为你可以尝试向那里传递类似 Future
的东西(即使 Future
是不合法的),这是渴望的,所以你会最终一次又一次地评估同一件事。至少通过名称参数,您有机会向那里传递副作用随机的配方。当然,如果我们使用 Option
、List
作为保存我们“随机”数字的 monad,我们也应该期待有趣的结果。
正确的解决方案是使用一些东西来确保这个 F[A]
被惰性求值,并且每次你需要从内部获取一个值时,内部的任何副作用都会被求值。为此,您基本上必须使用一些 Effects 类型类,例如Sync
来自 Cats Effects。
def calculatePi[F[_]](iterations: Int)
(random: F[Double])
(implicit F: Sync[F]): F[Double] = {
...
}
calculatePi(10000)(Coeval( Random.nextDouble )).value
calculatePi(10000)(Task( Random.nextDouble )).runAsync
或者,如果您不太关心纯度,则可以传递副作用函数或对象而不是 F[Int]
来生成随机数。
// simplified, hardcoded F=Coeval
def calculatePi(iterations: Int)
(random: () => Double): Double = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations) = Coeval {
val x = random()
val y = random()
val isInCircle = (x * x + y * y) < 1.0
val newTotal = data.total + 1
val newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
Monad[Coeval].tailRecM(Iterations(0, 0))(step).value
}
关于scala - 在 scala 中估计 PI 的单子(monad)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55710492/
我试图从 monad 中提取一个值,但保留不依赖于 monad 的多态值。具体来说: foo :: (Monad mon, Ring a) => mon a foo = return 3 main :
我是haskell、函数式语言和monads的新手。 我已经搞砸了大约一个月;我读了 learn you a haskell 并且正在玩 snap 试图制作我的 haskell 网站。 但是有一些事情
好的,因此 writer monad 允许您将内容写入 [通常] 某种容器,并在最后取回该容器。在大多数实现中,“容器”实际上可以是任何幺半群。 现在,还有一个“读者”单子(monad)。您可能会认为
来自 a gentle introduction to Haskell ,有以下单子(monad)定律。谁能直观地解释它们的意思? return a >>= k = k a m
我正在寻找 monad 的创造性用途来学习。我在某处读到过 monad 已被用于人工智能,但作为一个 monad 新手,我不知道如何使用。 请包含源代码和示例用法的链接。否standard monad
我已经断断续续地使用 Haskell 好几年了;我对 monad 的工作方式、使用方式以及运算符的含义非常满意 (=>=)做。 但我仍然不知道如何谈论它们!是否有任何标准术语来描述他们所做的事情——改
我正在尝试学习基于标准 Haskell 库的 monad 转换器(mtl?转换器?不确定我下载的 Haskell 平台 - 7.4.1 附带了哪一个)。 我相信我注意到的是每个 monad 转换器定义
背景 我正在阅读《大多数》Adequate Guide to Functional Programming并进行所有练习。我正在阅读第 9 章,Monadic Onions,但我在练习中遇到了困难。
有谁知道 C++ 中的一个好的 monad 模板库。也许,它提供了一些您会在 Haskell 中看到的常见单子(monad),例如 Maybe。 最佳答案 类似 Maybe 的东西可以在 Boost.
wiki.haskell.org 上的 99 个 Haskell 问题中的第 6 个提供了一种单子(monad)方法来测试列表(类型为 [a] )是否为回文: isPalindromeM :: (Eq
我一直在尝试围绕单子(monad)的概念进行思考,并且一直在尝试以下示例: 我有一个 Editor数据类型,表示文本文档的状态和一些处理它的函数。 data Editor = Editor { l
我一直在尝试找到任何讨论何时应该优先使用单子(monad)而不是 Actor (在并发场景中),但我什么也没找到。特别是,我想知道响应式(Reactive)扩展(LINQ to Events)与 F#
我在 Haskell 有一些经验,目前正在学习 Scala。我想知道Scala中是否有与Monads等效的东西? 最佳答案 您可能想查看 scalaz ;它受到 Haskell 的强烈影响。事实上,经
前几天我在谈论函数式编程——尤其是 Haskell 和一些 Java/Scala 人,他们问我什么是 Monad,它们在哪里是必要的。 好吧,定义和例子并不难 - Maybe Monad , IO M
我读过这篇 Q&A但不明白范畴论部分。 到目前为止,这是我的推理:当我查看类型时 F (a -> b) -> F a -> F b (a -> M b) -> M a -> M b a -> F a
import Debug.Trace main = do trace "Main function parses, and returns - " "0" return () 这会引发错误,
在页面 http://www.haskell.org/haskellwiki/Pointfree#Tool_support ,它谈到了 (->) a monad。 这个单子(monad)是什么?符号的
是 x >>= f相当于 retract (liftF x >>= liftF . f) ? 也就是说,从同样是 Monad 的 Functor 构建的自由 monad 的 monad 实例是否将具有
下面是谁先说的? A monad is just a monoid in the category of endofunctors, what's the problem? 在不太重要的一点上,这是真
我大致熟悉 monads 的概念和 arrows如函数式编程中所使用的那样。我还了解到它们可以用来解决类似的问题。 但是,我仍然对如何在任何给定情况下选择使用哪个感到有点困惑。 什么时候应该使用 mo
我是一名优秀的程序员,十分优秀!