This is a followup post to: Functional Swift: Fold it, baby!

The Accumulator Value

A small tip I forgot to mention about the initial accumulator value. Often times you can think of it as the neutral element of the operation you pass to fold. For example in the sum function the operation is addition. To not affect the final solution by the initial accumulator you use the neutral element to addition, which is zero.

More Variants of Fold

Speaking of the initial accumulator value, there is a version of fold that uses the first element of the list as its initial accumulator called foldl1. And these two versions of fold can be reversed so that the list is processed from right to left, foldr and foldr1.

foldl1

Like foldl but with the first element as the starting accumulator.

func foldl1<A>(list: Array<A>, f: (A, A) -> A) -> A {  
    return foldl(list.head!, list: list.tail!, f: f)
}

foldr

Fold from right to left, starting with the last element of the list. Note how the parameter order of the processing function is reversed to reflect the right to left notion.

extension Array {  
    var initial: Array<Element>? {
        get {
            if self.empty() { return nil }
            return Array(dropLast(self))
        }
    }
}

func foldr<A,B>(acc: A, list: Array<B>, f: (B, A) -> A) -> A {  
    if list.empty() { return acc }
    return foldr(f(list.last!, acc), list: list.initial!, f: f);
}

foldr1

Like foldr but with the last element as the starting accumulator.

func foldr1<A>(list: Array<A>, f: (A, A) -> A) -> A {  
    return foldr(list.last!, list: list.initial!, f: f)
}

  1. Functional Swift: Fold it, baby!
  2. Learn You a Haskell for Great Good!
  3. Gist of code examples