diff --git a/alleycats-core/src/main/scala/alleycats/std/all.scala b/alleycats-core/src/main/scala/alleycats/std/all.scala index a0f63e9584..0190bd913f 100644 --- a/alleycats-core/src/main/scala/alleycats/std/all.scala +++ b/alleycats-core/src/main/scala/alleycats/std/all.scala @@ -15,3 +15,4 @@ import export._ with LegacyTryInstances with LegacyIterableInstances with MapInstances + with MapInstancesBinCompat0 diff --git a/alleycats-core/src/main/scala/alleycats/std/map.scala b/alleycats-core/src/main/scala/alleycats/std/map.scala index 63b9d7839d..2cd69cef9d 100644 --- a/alleycats-core/src/main/scala/alleycats/std/map.scala +++ b/alleycats-core/src/main/scala/alleycats/std/map.scala @@ -3,7 +3,7 @@ package std import cats._ -object map extends MapInstances +object map extends MapInstances with MapInstancesBinCompat0 trait MapInstances { @@ -59,3 +59,21 @@ trait MapInstances { collectFirst(fa)(Function.unlift(f)) } } + +trait MapInstancesBinCompat0 extends MapInstances { + implicit def mapTraverseFilter[K]: TraverseFilter[Map[K, ?]] = + new TraverseFilter[Map[K, ?]] { + def traverse: Traverse[Map[K, ?]] = alleycatsStdInstancesForMap + + def traverseFilter[G[_], A, B](fa: Map[K, A])(f: A => G[Option[B]])(implicit G: Applicative[G]): G[Map[K, B]] = { + val gba: Eval[G[Map[K, B]]] = Always(G.pure(Map.empty)) + Foldable + .iterateRight(fa, gba) { (kv, lbuf) => + G.map2Eval(f(kv._2), lbuf)({ (ob, buf) => + ob.fold(buf)(b => buf + (kv._1 -> b)) + }) + } + .value + } + } +} diff --git a/alleycats-tests/src/test/scala/alleycats/tests/MapSuite.scala b/alleycats-tests/src/test/scala/alleycats/tests/MapSuite.scala index 7a0ff1a9f3..2e932950e8 100644 --- a/alleycats-tests/src/test/scala/alleycats/tests/MapSuite.scala +++ b/alleycats-tests/src/test/scala/alleycats/tests/MapSuite.scala @@ -1,8 +1,12 @@ package alleycats.tests -import cats.laws.discipline.SerializableTests +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.{SerializableTests, TraverseFilterTests} import cats.Traverse +import alleycats.std.all._ class MapSuite extends AlleycatsSuite { checkAll("Traverse[Map[Int, ?]]", SerializableTests.serializable(Traverse[Map[Int, ?]])) + + checkAll("TraverseFilter[Map[Int, ?]]", TraverseFilterTests[Map[Int, ?]].traverseFilter[Int, Int, Int]) }