Haskell 是否存在“span”和“foldl';”的优化组合,还是GHC会优化组合?

Haskell 是否存在“span”和“foldl';”的优化组合,还是GHC会优化组合?,haskell,optimization,ghc,fold,Haskell,Optimization,Ghc,Fold,假设我想把一个列表中的所有元素相加到第一个负数,但不包括第一个负数,然后返回该数字和列表的其余部分。实现这一点的简单方法是 addPos l = s `seq` (s,back) where (front, back) = span (>= 0) l s = sum front addPos l=s`seq`(s,背面) 哪里 (前、后)=跨度(>=0)l s=总前沿 其中,seq应确保没有人通过在总和之前强制后退而意外地造成巨大的撞击 然而,我很好奇,GHC是否足够聪明,可

假设我想把一个列表中的所有元素相加到第一个负数,但不包括第一个负数,然后返回该数字和列表的其余部分。实现这一点的简单方法是

addPos l = s `seq` (s,back) where (front, back) = span (>= 0) l s = sum front addPos l=s`seq`(s,背面) 哪里 (前、后)=跨度(>=0)l s=总前沿 其中,
seq
应确保没有人通过在总和之前强制后退而意外地造成巨大的撞击


然而,我很好奇,GHC是否足够聪明,可以避免创建中间排名。另外,有人能解释一下(如果有的话)它是如何计算出它可以严格地累加成和的吗?前奏曲定义使用foldl而不是foldl',GHC定义看起来是等效的。

当我们谈论编译器优化中间列表时,通常我们谈论的是在GHC的
规则中实现的“融合”;您可以了解它是如何工作的,哪些列表函数是“好的消费者”和“生产者”

不幸的是,
span
看起来并不是一个“好制作人”。您可以通过要求查看GHC的核心输出来查看,并获得使用
GHC-O2-ddump siml-dsuppress模块前缀-dsuppress uniques-ddump core stats-ddump inlinings-ddump rule firings test.hs触发的规则列表

下面是一个已清理的输出:

Rule fired: Class op >=
Rule fired: SPEC Data.List.sum
Inlining done: geInt{v r3n} [gid]
Inlining done: sum_sum1{v rkV} [gid]
Inlining done: span{v r1Q} [gid]
Inlining done: sum_sum'1{v rl6} [gid]

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 24, types: 27, coercions: 0}

addPos1 :: Int -> Bool
addPos1 = \ (ds :: Int) -> case ds of _ { I# x -> >=# x 0 }

addPos [InlPrag=INLINE[0]] :: [Int] -> (Int, [Int])
addPos =
  \ (w :: [Int]) ->
    case $wspan @ Int addPos1 w of _ { (# ww1, ww2 #) ->
    case $wsum' ww1 0 of ww3 { __DEFAULT -> (I# ww3, ww2) }
    }
您可以看到,我们将某种类型的重写/专门化
span
,后跟一个


您可能会看到
vector
库是否可以将它们融合在一起,或者查看性能如何比较以获得乐趣。

“另外,有人能解释一下(如果有的话)它是如何计算出它可以严格累加的吗?”foldl是内联的,plus是严格的。严格性分析器完成其他所有工作。由于这个原因,很少需要foldl。span或多或少是“takeWhile”pxs,“dropWhile”pxs。但是,如果addPlus出现性能问题,为什么需要使用span?正如杰伯里曼所说的那样研究这个问题。谢谢你的研究!当然,下一个问题是,是否有一个标准函数可以将
foldl
span
组合在一起,还是我只需要自己滚动。