问题标签 [strictness]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - seq 如何评估 Haskell 中的无限列表?
据说 Haskell seq函数强制评估其第一个参数并返回第二个参数。它用于增加表达式评估的严格性。那么以下如何简单地返回 5:
它不应该被困在试图构建一个无限列表吗?
haskell - 为什么 HashMap 在一系列插入时不是正常形式?
我一直在尝试使用 ghc-heap-view 包和它提供的实用程序来确保 Haskell 程序的内存模型的严格性,当我注意到我HashMap
的 s 在一系列插入时似乎不在 NF 中. 我尝试打印堆树,确实显示了一些 thunk。然后我尝试了另一种插入元素的方法(使用union
and singleton
),这次它很严格。
有人可以解释为什么会这样,并建议我是否可以做任何事情来使insert
行为与其他方法相同?
这是我的测试代码:
这是输出:
haskell - 是否可以在 Haskell 中实现此功能?
在页面https://en.wikibooks.org/wiki/Haskell/Denotational_semantics#Pattern_Matching有以下练习:
考虑具有
or
以下属性的两个布尔参数的函数:
- 或⊥ ⊥ = ⊥</li>
- 或真 ⊥ = 真
- 或 ⊥ 真 = 真
- 或假 y = y
- 或 x 假 = x
这个函数是联合严格性的另一个例子,但更清晰:如果两个参数都是(至少当我们将参数限制为 True 和 ⊥ 时),结果只是 ⊥。在 Haskell 中可以实现这样的功能吗?
该函数可以用下表表示:
根据https://en.wikibooks.org/wiki/Haskell/Denotational_semantics#Monotonicity中给出的定义,这个函数是单调的,所以我认为没有理由排除在 Haskell 中实现这个函数的可能性。尽管如此,我没有看到实现它的方法。
练习的答案是什么?
PS:我知道答案是“不,你不能”。我正在寻找的是一个严格的证明。我觉得我错过了一些关于可以定义哪些功能的重要限制。绝对不是所有的单调函数。
haskell - 惰性状态转换器在 2D 递归中急切地消耗惰性列表
我正在使用状态转换器在 2D 递归游走的每个点对数据集进行随机采样,从而输出一个 2D 样本网格列表,这些样本一起满足一个条件。我想懒洋洋地从结果中提取,但我的方法反而在我提取第一个结果之前在每个点都耗尽了整个数据集。
具体来说,考虑这个程序:
(x, y)
该程序从到遍历矩形网格(0, 0)
并对所有结果求和,包括状态单子列表之一的值:st
读取和推进其状态的非平凡转换器,或平凡转换器unst
。有趣的是该算法是否探索了st
和的头部unst
。
在呈现的代码中,它抛出undefined
. 我将此归结为我对链接转换顺序的错误设计,特别是状态处理的问题,因为使用unst
(即从状态转换中分离结果)确实会产生结果。但是,我随后发现,即使使用状态转换器,一维递归也可以保持惰性(删除广度步骤b <- walk...
并将liftM2
块交换为fmap
)。
如果我们trace (show (x, y))
,我们还会看到它在触发之前确实遍历了整个网格:
我怀疑我sequence
在这里的使用是错误的,但是由于 monad 的选择和 walk 的维度会影响其成功,我不能广泛地说sequence
ing 转换本身就是严格性的来源。
是什么导致了 1D 和 2D 递归之间的严格性差异,我怎样才能实现我想要的惰性?
haskell - Haskell 中的求值是如何工作的,对于有约束的表达式
假设我用 GHCi 写:
GHCix = 3
按自然预期打印。
然而,
产量x = _
这两个表达式之间的唯一区别是它们的类型(Integer
vs Num a => a
)。我的问题是到底发生了什么,为什么x
在后一个例子中似乎没有评估。
haskell - GHCi 中的严格列表评估
考虑程序:
使用 GHCi 运行它,然后输入:sprint l
and:sprint l'
将显示两个列表都未评估。但是,在运行length l
然后length l'
再次使用之后sprint
:
和
我已经进行了类似的实验并尝试将变量绑定到 GHCi 中的列表let
,但是只有在l
(如上在程序顶层中定义)的情况下,列表总是被完全评估。
这些行为都指向优化功能,但是我想知道是否有更详尽的答案(策略)“幕后”。
haskell - 为什么 foldr' 不如 foldl' 严格?
考虑以下各种尝试last
:
这对我来说是有道理的,foldl
而且foldr
两者都有效,因为它们的累加器并不严格,而对我来说,这并不严格foldl'
,因为它是有道理的。但为什么foldr'
有效?它的累加器不应该也很严格吗?
haskell - 如果我们用它写下 mfix,liftM 对 Functor 实例是否过于严格?
fmap
对于Monads
通常默认为liftM
:
然而,正如人们所看到的,它使用绑定(如右手去糖成m1 >>= \ x1 -> return (f x1)
)。我想知道这样的 a 是否fmap
可以用于为mfix
具有严格>>=
运算符的单子写下来。更准确地说,我想知道Control.Arrow.loop
(再次)的以下实现。
我使用的 monad 是Identity
,但它会在绑定发生时强制其中的任何内容seq
。
我的直觉是可以的,可以用。我认为我们只会在两种情况下遇到问题:
k
我们申请mfix
/myMfix
是严格的。- 我们申请
mfix
/myMfix
。return
这两种情况都相当简单,我们一开始并不期望任何收敛的结果。我相信其他案例可以在不强制反馈的情况下强制进行WHNF。
我的直觉正确吗?如果没有,可以举一个失败的例子吗?
haskell - 避免单子展开生成的稀疏评估列表中的thunk
我有一个模拟库,它使用包装在 monad 中的 FFI M
,并带有上下文。所有的外来函数都是纯函数,所以我决定让 monad 变得惰性,这通常便于流控制。我将我的模拟表示为一个模拟框架列表,我可以通过写入文件或以图形方式显示框架来使用它们。
每个帧都包含一个新类型包装ForeignPtr
的元组,我可以使用它提升到我的 Haskell 表示
lift :: Frame -> M HFrame
由于我的模拟中的时间步很短,我只想查看n
我使用的每一帧
所以我的代码看起来像
现在,问题是随着我的增加n
,一个thunk 建立起来。我尝试了几种不同的方法来严格评估 中的每一帧simulation
,但我还没有弄清楚如何去做。ForeignPtr
似乎没有NFData
实例,所以我不能使用deepseq
,但是我所有的尝试seq
,包括seq
在元组中的每个元素上使用,都没有明显的效果。
编辑:
根据要求,我提供了更多细节,我最初排除了这些细节,因为我认为它们可能主要是这个问题的噪音。
单子
所有的外来函数都从IO
withunsafeLiftFromIO
steps
它们本身应该是任意的(Frame c -> FT c (Frame c))
,因此严格性最好在更高级别的代码中。
编辑2:
我现在尝试使用Streamly
,但是问题仍然存在,所以我认为问题确实是找到一种严格评估ForeignPtr
s 的方法。
当前实现:
编辑3:
澄清症状以及我如何诊断问题。
该库调用OpenCL
在 GPU 上运行的函数。我确信指针的释放得到了正确处理 - ForeignPtr
s 具有正确的释放功能,并且内存使用与总数无关,steps
只要这个数字大于n
. 我发现 GPU 上的内存使用基本上与n
. 我用于此测试的消费者是
为了我的流畅实施,以及
对于原始实现。两者都应该连续消耗流。我已经生成了steps
用于测试的replicate
.
我不确定如何更精确地分析 GPU 上的内存使用情况。系统内存使用在这里不是问题。
更新:我开始认为这不是严格问题,而是 GC 问题。运行时系统不知道在 GPU 上分配的内存大小,因此不知道收集指针,当 CPU 端也有东西时,这不是问题,因为这会产生分配同样,激活 GC。n
这可以解释稍微不确定的内存使用情况,但与我所看到的线性相关。如何很好地解决这个问题是另一个问题,但我怀疑我的代码将会进行重大改革。