访问累加器& `foldl`中的元素

时间:2014-04-14 02:25:09

标签: scala haskell fold

在Scala的foldLeft中,我知道如何访问Scala中的accumulatorelement值,但不知道Haskell。

我可以使用foldLeft找出1到100之间的数字,当除以3时,有多少数字的余数为1:

scala> List.range(1, 101).foldLeft(0){ (acc, elem) =>
     |    if (elem % 3 == 1) acc + 1
     |    else acc
     | }
res2: Int = 33

我如何在Haskell中做同样的事情?

3 个答案:

答案 0 :(得分:5)

基本上是一对一的对应关系:

mySum :: [Int] -> Int
mySum xs = foldl (\acc elem ->
    if elem `mod` 3 == 1
        then acc + 1
        else acc
    ) 0 xs

除了参数的语法和顺序之外,没有真正的区别。


对于未来的读者,建议在实践中避免使用foldl。由于foldl实施中的懒惰,大型列表可能发生空间泄漏。相反,有一个严格的版本foldl'可以用作替代版本或右侧折叠foldr,它具有位格式:

mySum xs = foldr (\elem acc ->    -- order of arguments swapped
    if elem `mod` 3 == 1
        then acc + 1
        else acc
    ) 0 xs

答案 1 :(得分:3)

这是您的Scala代码直接转换为Haskell:

foldl (\acc x -> if x `mod` 3 == 1 then acc + 1 else acc) 0 [1..100]

在Haskell中,由于它的懒惰using foldl usually is not a good idea,更好的选择是foldl'foldr,这里是foldr版本:

foldr (\x acc -> if x `mod` 3 == 1 then acc + 1 else acc) 0 [1..100]

答案 2 :(得分:0)

它非常相似:

foldl (\acc x -> if (x `mod` 3 == 1) then acc + 1 else acc) 0 [1..100]

foldl的第一个参数是lambda,第二个是累加器0,第三个是值的范围。

请参阅this question以了解foldl,foldl'之间的区别。和折叠。