Add SortedMap and SortedSet instances/Move Set and Map instances to Alleycats#1972
Conversation
| else fb.map(fb => map2(fa, fb)(f)) | ||
|
|
||
| override def ap[A, B](ff: SortedMap[K, A => B])(fa: SortedMap[K, A]): SortedMap[K, B] = | ||
| ??? //fa.flatMap { case (k, a) => ff.get(k).map(f => (k, f(a))) }(scala.collection.breakOut) |
There was a problem hiding this comment.
still WIP? same below
There was a problem hiding this comment.
Yes, sorry. I meant to state so in the description 😅
df28b39 to
24fb152
Compare
| var a, b, n = 0 | ||
| var c = 1; | ||
| x foreach { case (k, v) => | ||
| // use the default hash on keys because that's what Scala's Map does |
There was a problem hiding this comment.
I don't think we want to do that here actually. Map[K, V] needs to do this because the hash in question in a Map[K, V] is the .hashCode. But I think we can be unconstrained on a SortedMap since it is only using our Order typeclass.
| fa.foldLeft(b) { case (x, (k, a)) => f(x, a)} | ||
|
|
||
| def foldRight[A, B](fa: SortedMap[K, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = | ||
| Foldable.iterateRight(fa.values.iterator, lb)(f) |
There was a problem hiding this comment.
I thought this was actually unsafe since it captures a mutable iterator? I think to make it safe, it needs to have () => Iterator[A] which it can call to get a new one each time (which is another way of saying the Iterable[A] and it calls .iterator internally.
We had some bug related to this in the past. Not sure why we didn't fix Foldable.iterateRight. Actually, it was related, but not exactly the same. See #1716.
24fb152 to
5ec40c9
Compare
5ec40c9 to
a1705a9
Compare
Codecov Report
@@ Coverage Diff @@
## master #1972 +/- ##
==========================================
- Coverage 95.49% 95.24% -0.25%
==========================================
Files 298 301 +3
Lines 4814 4922 +108
Branches 120 123 +3
==========================================
+ Hits 4597 4688 +91
- Misses 217 234 +17
Continue to review full report at Codecov.
|
|
Damn there's no mutable |
035461b to
c226af6
Compare
c226af6 to
26c1d9a
Compare
|
So the tests fail for 2.11 and earlier for some reason. Will have to investigate |
26c1d9a to
9c76d12
Compare
9c76d12 to
62ec8d4
Compare
58e6907 to
fb37bba
Compare
fb37bba to
a5948aa
Compare
…into LukaJCB-add-sorted-instances
|
|
||
| test("Foldable[Set].foldM stack safety") { | ||
| checkFoldMStackSafety[Set](_.toSet) | ||
| } |
There was a problem hiding this comment.
shall we replace these two foldMStackSafety tests with SortedSet and SortedMap ones?
|
|
||
| test("ParTraverse_ identity should be equivalent to parSequence_") { | ||
| forAll { es: Set[Either[String, Int]] => | ||
| forAll { es: List[Either[String, Int]] => |
There was a problem hiding this comment.
why not use SortedSet? (Either has Order instance)
| type StringMap[A] = Map[String, A] | ||
| val intMap: StringMap[Int] = Map("one" -> 1, "two" -> 2, "six" -> 6, "eight" -> 8) | ||
| intMap.traverse(validate) should === (Either.left("6 is greater than 5")) | ||
| checkAndResetCount(3) |
There was a problem hiding this comment.
Not sure what this regression test is about, do you know? If neither of us are sure maybe we should replace it with a sortedMap one?
There was a problem hiding this comment.
Apparently it's about #513. I had to adjust this test slightly, because the order of the Strings matter now, so it wouldn't work if we just change the type of the collection :)
|
Everything should be addressed now 🎉 Thanks everyone! |
| implicit def catsStdInstancesForMap[K]: Traverse[Map[K, ?]] with FlatMap[Map[K, ?]] = | ||
| new Traverse[Map[K, ?]] with FlatMap[Map[K, ?]] { | ||
|
|
||
| def traverse[G[_], A, B](fa: Map[K, A])(f: A => G[B])(implicit G: Applicative[G]): G[Map[K, B]] = { |
There was a problem hiding this comment.
Can we add some law that this violates? I hate to remove it if we don’t actually have a law that it violates. I think we can write some (the original ticket had an example). I fear we could have other lawless instances without a law.
|
|
||
| def combineK[A](x: Set[A], y: Set[A]): Set[A] = x | y | ||
|
|
||
| def foldLeft[A, B](fa: Set[A], b: B)(f: (B, A) => B): B = |
There was a problem hiding this comment.
Same concern here about adding a law that this violates. Maybe a == b implies toList(a) == toList(b)
There was a problem hiding this comment.
We're going to need to spend some more time to find something. That one won't work, because that way e.g
Either.Left(123) =!= Either.Left(-30) would imply List() =!= List()
There was a problem hiding this comment.
I'm not sure if it's the best solution but I worked around it, by only considering the positive case. I.e a == b implies toList(a) == toList(b) but not a != b implies toList(a) != toList(b)
There was a problem hiding this comment.
This is what I meant (which is why I didn’t say (a == b) == (a.toList == b.toList))
59a760a to
8745b55
Compare
|
This looks good to me. One question: do you know if this test would actually have caught Map/Set problems? I guess it must have since small maps/sets are just tuples and created in the order added. |
|
Yes I tested these on master and they failed for set/map. |
|
Although to be fair, I ran into some problems because it might not actually generate a situation where the tests fail every time because it's rare that they generate two different collections with the same values but different orderings. |
e32a461 to
37e36ea
Compare
realized that the Foldable test could be improved.
SortedMap and SortedSet instances
|
I couldn't think of a way to write the law so that will consistently fail on unordered data types either. Another option we have is to simply remove the |
SortedMap and SortedSet instancesSortedMap and SortedSet instances/Move Set and Map instances to Alleycats
|
thanks so much for pushing this through |
Should fix #1966