- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是否可以在状态单子(monad)中以恒定的堆栈和堆空间执行折叠?还是一种不同的功能技术更适合我的问题?
接下来的部分描述了这个问题和一个激励用例。我正在使用 Scala,但也欢迎使用 Haskell 中的解决方案。
折叠 State
Monad 填满堆
假设 Scalaz 7。考虑状态单子(monad)中的单子(monad)折叠。为了避免堆栈溢出,我们将蹦床折叠。
import scalaz._
import Scalaz._
import scalaz.std.iterable._
import Free.Trampoline
type TrampolinedState[S, B] = StateT[Trampoline, S, B] // monad type constructor
type S = Int // state is an integer
type M[B] = TrampolinedState[S, B] // our trampolined state monad
type R = Int // or some other monoid
val col: Iterable[R] = largeIterableofRs() // defined elsewhere
val (count, sum): (S, R) = col.foldLeftM[M, R](Monoid[R].zero){
(acc: R, x: R) => StateT[Trampoline, S, R] {
s: S => Trampoline.done {
(s + 1, Monoid[R].append(acc, x))
}
}
} run 0 run
// In Scalaz 7, foldLeftM is implemented in terms of foldRight, which in turn
// is a reversed.foldLeft. This pulls the whole collection into memory and kills
// the heap. Ignore this heap overflow. We could reimplement foldLeftM to avoid
// this overflow or use a foldRightM instead.
// Our real issue is the heap used by the unexecuted State mobits.
col
,这将填满堆。
x: R
参数)创建一个闭包(一个 State mobit),填充堆。在
run 0
之前,这些都无法评估。被执行,提供初始状态。
run
之后延迟执行?这样,下一个
x: R
直到之前的闭包被评估并适合垃圾收集之后才会创建闭包。
k
集合中的项目太大而无法放入内存。在 Scala 中,这样的函数可能是
def sample[A](col: TraversableOnce[A])(k: Int): Vector[A]
TraversableOnce
类型可以这样使用
val tenRandomInts = (Int.Min to Int.Max) sample 10
sample
所做的工作本质上是
fold
:
def sample[A](col: Traversable[A])(k: Int): Vector[A] = {
col.foldLeft(Vector()){update(k)(_: Vector[A], _: A)}
}
update
是有状态的;这取决于
n
,已经看到的项目数。 (它也依赖于一个 RNG,但为了简单起见,我假设它是全局的和有状态的。用于处理
n
的技术将很容易扩展。)。那么如何处理这种状态呢?
/* Impure version of update function */
def update[A](k: Int) = new Function2[Vector[A], A, Vector[A]] {
var n = 0
def apply(sample: Vector[A], x: A): Vector[A] = {
n += 1
algorithmR(k, n, acc, x)
}
}
def algorithmR(k: Int, n: Int, acc: Vector[A], x: A): Vector[A] = {
if (sample.size < k) {
sample :+ x // must keep first k elements
} else {
val r = rand.nextInt(n) + 1 // for simplicity, rand is global/stateful
if (r <= k)
sample.updated(r - 1, x) // sample is 0-index
else
sample
}
}
update
必拍
n
作为附加参数并返回新值以及更新的样本。我们可以包括
n
在隐式状态下,折叠累加器,例如,
(col.foldLeft ((0, Vector())) (update(k)(_: (Int, Vector[A]), _: A)))._2
import scalaz._
import Scalaz._
import scalaz.std.iterable_
Iterable[A]
进行操作, 因为 Scalaz 不支持
Traversable
的单子(monad)折叠.
sample
现在定义
// sample using State monad
def sample[A](col: Iterable[A])(k: Int): Vector[A] = {
type M[B] = State[Int, B]
// foldLeftM is implemented using foldRight, which must reverse `col`, blowing
// the heap for large `col`. Ignore this issue for now.
// foldLeftM could be implemented differently or we could switch to
// foldRightM, implemented using foldLeft.
col.foldLeftM[M, Vector[A]](Vector())(update(k)(_: Vector[A], _: A)) eval 0
}
// update using State monad
def update(k: Int) = {
(acc: Vector[A], x: A) => State[Int, Vector[A]] {
n => (n + 1, algorithmR(k, n + 1, acc, x)) // algR same as impure solution
}
}
sample
就是现在
// sample using trampolined State monad
def sample[A](col: Iterable[A])(k: Int): Vector[A] = {
import Free.Trampoline
type TrampolinedState[S, B] = StateT[Trampoline, S, B]
type M[B] = TrampolinedState[Int, B]
// Same caveat about foldLeftM using foldRight and blowing the heap
// applies here. Ignore for now. This solution blows the heap anyway;
// let's fix that issue first.
col.foldLeftM[M, Vector[A]](Vector())(update(k)(_: Vector[A], _: A)) eval 0 run
}
// update using trampolined State monad
def update(k: Int) = {
(acc: Vector[A], x: A) => StateT[Trampoline, Int, Vector[A]] {
n => Trampoline.done { (n + 1, algorithmR(k, n + 1, acc, x) }
}
}
x: A
参数),甚至在蹦床运行之前消耗堆。 (FWIW,State 版本也有这个问题;堆栈溢出首先出现在较小的集合中。)
最佳答案
Our real issue is the heap used by the unexecuted State mobits.
foldLeftM
和
foldRightM
强制整个集合。不纯解决方案的一个副作用是您正在释放内存。在“纯功能”解决方案中,您不会在任何地方这样做。
Iterable
的使用忽略了一个关键细节:什么样的收藏
col
实际上是,它的元素是如何创建的,以及它们是如何被丢弃的。因此,
foldLeftM
必然如此。在
Iterable
.它可能过于严格,并且您将整个集合强制放入内存。例如,如果它是
Stream
,那么只要你坚持
col
到目前为止强制执行的所有元素都将在内存中。如果是其他类型的懒惰
Iterable
没有记住它的元素,那么折叠仍然太严格。
EphemeralStream
尝试了您的第一个示例没有看到任何显着的堆压力,即使它显然具有相同的“未执行状态 mobits”。不同之处在于
EphemeralStream
的元素被弱引用,其
foldRight
不会强制整个流。
Foldable.foldr
,那么您将看不到有问题的行为,因为它与第二个参数中惰性的函数折叠在一起。当你调用 fold 时,你希望它立即返回一个看起来像这样的暂停:
Suspend(() => head |+| tail.foldRightM(...))
def foldM[M[_]:Monad,A,B](a: A, bs: Iterable[B])(f: (A, B) => M[A]): M[A] =
if (bs.isEmpty) Monad[M].point(a)
else Monad[M].bind(f(a, bs.head))(fax => foldM(fax, bs.tail)(f))
val MS = StateT.stateTMonadState[Int, Trampoline]
import MS._
foldM[M,R,Int](Monoid[R].zero, col) {
(x, r) => modify(_ + 1) map (_ => Monoid[R].append(x, r))
} run 0 run
M
,这将在恒定堆中运行,但会溢出堆栈以获取非蹦床单子(monad)。
Iterable
对于太大而无法放入内存的数据,这不是一个好的抽象。 当然,你可以编写一个命令式的副作用程序,在每次迭代后显式丢弃元素或使用惰性右折叠。在您想将该程序与另一个程序组合之前,这很有效。而且我假设您在
State
中调查这样做的全部原因monad 一开始是为了获得组合性。
Reducer
, Monoid
, 及其组合,然后在命令式显式释放循环(或蹦床惰性右折叠)中运行作为最后一步,之后组合是不可能的或预期的。 Iteratee
组合和单子(monad)Enumerator
s 喂它们。 关于scala - 状态单子(monad)在恒定空间(堆和堆栈)中的单子(monad)折叠?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20756436/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!