Skip to content

Commit

Permalink
Add foldMapWithKey to IMap
Browse files Browse the repository at this point in the history
Add a general foldMap function except that key is used for an arg
of a foldMap function.[1]
As mentioned by foxik[2], add a special case in foldMapWithKey when
foldMapping a leaf, which allows us not to foldMap redundantly.

[1] haskell/containers#24
[2] haskell/containers@e60634d
  • Loading branch information
monkey-mas committed May 23, 2016
1 parent c58a6f9 commit 1824476
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
10 changes: 10 additions & 0 deletions core/src/main/scala/scalaz/Map.scala
Expand Up @@ -610,6 +610,16 @@ sealed abstract class ==>>[A, B] {
l.foldrWithKey(f(kx, x, r.foldrWithKey(z)(f)))(f)
}

def foldMapWithKey[C](f: (A, B) => C)(implicit F: Monoid[C]): C =
this match {
case Tip() =>
F.zero
case Bin(k, x, Tip(), Tip()) =>
f(k, x)
case Bin(k, x, l, r) =>
F.append(l.foldMapWithKey(f), F.append(f(k, x), r.foldMapWithKey(f)))
}

/* Unions */
def union(other: A ==>> B)(implicit k: Order[A]): A ==>> B = {
def hedgeUnion(blo: Option[A], bhi: Option[A], m1: A ==>> B, m2: A ==>> B): A ==>> B =
Expand Down
11 changes: 11 additions & 0 deletions tests/src/test/scala/scalaz/MapTest.scala
Expand Up @@ -777,6 +777,17 @@ object MapTest extends SpecLite {
val f = (k: Int, a: String, result: String) => result + "(" + k.toString + ":" + a + ")"
fromList(List(5 -> "a", 3 -> "b")).foldrWithKey("Map: ")(f) must_== "Map: (5:a)(3:b)"
}

"foldMapWithKey" ! forAll { a: Byte ==>> Byte =>
val intAddition = new Monoid[Int] {
def zero: Int = 0
def append(f: Int, f2: => Int): Int = f + f2
}
val f = (i: Byte, j: Byte) => i.toInt + j.toInt
val res = a.toList.foldLeft(0: Int)((acc, kv) => acc + kv._1.toInt + kv._2.toInt)

a.foldMapWithKey(f) must_=== res
}
}

"==>> trim" should {
Expand Down

0 comments on commit 1824476

Please sign in to comment.