我很好奇如何优化这段代码:
fun n = (sum l, f $ f0 l, g $ g0 l)
where l = map h [1..n]
假设 , f
, f0
,g
和g0
都是h
昂贵的,但创建和存储的l
成本非常高。
如所写,l
存储直到返回的元组被完全评估或垃圾收集。相反,length l
,f0 l
和g0 l
应该在其中任何一个被执行时都被执行,但是f
应该g
被延迟。
看来这种行为可以通过编写来解决:
fun n = a `seq` b `seq` c `seq` (a, f b, g c)
where
l = map h [1..n]
a = sum l
b = inline f0 $ l
c = inline g0 $ l
或非常相似:
fun n = (a,b,c) `deepSeq` (a, f b, g c)
where ...
我们也许可以指定一堆内部类型来实现相同的效果,这看起来很痛苦。还有其他选择吗?
另外,我显然希望我inline
的 s 编译器将sum
, f0
, 和融合g0
到一个循环中,该循环逐项构造和l
使用。我可以通过手动内联来明确这一点,但这很糟糕。有没有办法明确地阻止列表l
被创建和/或强制内联?如果在编译期间内联或融合失败,可能会产生警告或错误的编译指示?
顺便说一句,我很好奇为什么seq
, inline
,lazy
等都let x = x in x
在 Prelude 中定义。这只是为了给他们一个定义让编译器覆盖吗?