Skip to content

Instantly share code, notes, and snippets.

@chrislewis
Created July 9, 2014 03:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrislewis/71f0a384ed5426646720 to your computer and use it in GitHub Desktop.
Save chrislewis/71f0a384ed5426646720 to your computer and use it in GitHub Desktop.
/*
CanBuildFrom is easily abused such that the ubiquitous higher order function
map can be repurposed as fold. This is not good; this example demonstrates
a design flaw, not a strength.
*/
import scala.language.postfixOps
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
import scala.math.Numeric
object MapIsFold {
/** Given a higher kind K, a zero value of type B, and a function combining an
A and B into a B, yield a CanBuildFrom that produces a Builder which will
accumulate A values into a single B value. */
def cbf[K[_], A, B](zero: B, f: (A, B) => B) =
new CanBuildFrom[K[A], A, B] {
override def apply() = new Builder[A, B] {
private var i = zero
def +=(elem: A) = {
i = f(elem, i)
this
}
def clear() { i = zero }
def result() = i
}
override def apply(from: K[A]): Builder[A, B] = apply()
}
/** A function to lift implicitly available Numeric instances into
CanBuildFrom instances that support folding. */
implicit def catamorphicCbf[K[_], A](implicit n: Numeric[A]) =
cbf[K, A, A](n.zero, n.plus)
}
/*
scala> import MapIsFold._
import MapIsFold._
scala> List(1,2,3).map(1+)
res0: Int = 9
scala> Set(1,2,3).map(1+)
res1: Int = 9
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment