-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SortedMap
and SortedSet
instances/Move Set
and Map
instances to Alleycats
#1972
Changes from 19 commits
a1705a9
2ec0b0a
fef41c1
62ec8d4
ec82e5f
1bf9b94
8ff298e
a5948aa
32c9aa2
4e13e8e
9f0ef36
93f273a
16359a3
151412c
40f9de5
36eeada
4e6456a
8745b55
37e36ea
2aef355
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package alleycats | ||
package std | ||
|
||
import cats._ | ||
|
||
trait MapInstances { | ||
|
||
// toList is inconsistent. See https://github.com/typelevel/cats/issues/1831 | ||
implicit def alleycatsStdInstancesForMap[K]: Traverse[Map[K, ?]] = | ||
new Traverse[Map[K, ?]] { | ||
|
||
def traverse[G[_], A, B](fa: Map[K, A])(f: A => G[B])(implicit G: Applicative[G]): G[Map[K, B]] = { | ||
val gba: Eval[G[Map[K, B]]] = Always(G.pure(Map.empty)) | ||
val gbb = Foldable.iterateRight(fa, gba){ (kv, lbuf) => | ||
G.map2Eval(f(kv._2), lbuf)({ (b, buf) => buf + (kv._1 -> b)}) | ||
}.value | ||
G.map(gbb)(_.toMap) | ||
} | ||
|
||
override def map[A, B](fa: Map[K, A])(f: A => B): Map[K, B] = | ||
fa.map { case (k, a) => (k, f(a)) } | ||
|
||
def foldLeft[A, B](fa: Map[K, A], b: B)(f: (B, A) => B): B = | ||
fa.foldLeft(b) { case (x, (k, a)) => f(x, a)} | ||
|
||
def foldRight[A, B](fa: Map[K, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = | ||
Foldable.iterateRight(fa.values, lb)(f) | ||
|
||
override def size[A](fa: Map[K, A]): Long = fa.size.toLong | ||
|
||
override def get[A](fa: Map[K, A])(idx: Long): Option[A] = | ||
if (idx < 0L || Int.MaxValue < idx) None | ||
else { | ||
val n = idx.toInt | ||
if (n >= fa.size) None | ||
else Some(fa.valuesIterator.drop(n).next) | ||
} | ||
|
||
override def isEmpty[A](fa: Map[K, A]): Boolean = fa.isEmpty | ||
|
||
override def fold[A](fa: Map[K, A])(implicit A: Monoid[A]): A = | ||
A.combineAll(fa.values) | ||
|
||
override def toList[A](fa: Map[K, A]): List[A] = fa.values.toList | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package alleycats.tests | ||
|
||
import cats.laws.discipline.SerializableTests | ||
import cats.Traverse | ||
|
||
class MapSuite extends AlleycatsSuite { | ||
checkAll("Traverse[Map[Int, ?]]", SerializableTests.serializable(Traverse[Map[Int, ?]])) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package alleycats.tests | ||
|
||
import alleycats.laws.discipline._ | ||
import cats.Foldable | ||
import cats.kernel.laws.discipline.SerializableTests | ||
|
||
import alleycats.std.all._ | ||
|
||
class SetSuite extends AlleycatsSuite { | ||
checkAll("FlatMapRec[Set]", FlatMapRecTests[Set].tailRecM[Int]) | ||
|
||
checkAll("Foldable[Set]", SerializableTests.serializable(Foldable[Set])) | ||
} | ||
|
||
|
||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,17 @@ | ||
package cats | ||
package instances | ||
|
||
import scala.annotation.tailrec | ||
|
||
import cats.syntax.show._ | ||
|
||
trait SetInstances extends cats.kernel.instances.SetInstances { | ||
|
||
implicit val catsStdInstancesForSet: Foldable[Set] with MonoidK[Set] = | ||
new Foldable[Set] with MonoidK[Set] { | ||
implicit val catsStdInstancesForSet: MonoidK[Set] = | ||
new MonoidK[Set] { | ||
|
||
def empty[A]: Set[A] = Set.empty[A] | ||
|
||
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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're going to need to spend some more time to find something. That one won't work, because that way e.g There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if it's the best solution but I worked around it, by only considering the positive case. I.e There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I meant (which is why I didn’t say (a == b) == (a.toList == b.toList)) |
||
fa.foldLeft(b)(f) | ||
|
||
def foldRight[A, B](fa: Set[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = | ||
Foldable.iterateRight(fa, lb)(f) | ||
|
||
override def get[A](fa: Set[A])(idx: Long): Option[A] = { | ||
@tailrec | ||
def go(idx: Int, it: Iterator[A]): Option[A] = { | ||
if (it.hasNext) { | ||
if (idx == 0) Some(it.next) else { | ||
it.next | ||
go(idx - 1, it) | ||
} | ||
} else None | ||
} | ||
if (idx < Int.MaxValue && idx >= 0L) go(idx.toInt, fa.toIterator) else None | ||
} | ||
|
||
override def size[A](fa: Set[A]): Long = fa.size.toLong | ||
|
||
override def exists[A](fa: Set[A])(p: A => Boolean): Boolean = | ||
fa.exists(p) | ||
|
||
override def forall[A](fa: Set[A])(p: A => Boolean): Boolean = | ||
fa.forall(p) | ||
|
||
override def isEmpty[A](fa: Set[A]): Boolean = fa.isEmpty | ||
|
||
override def fold[A](fa: Set[A])(implicit A: Monoid[A]): A = A.combineAll(fa) | ||
|
||
override def toList[A](fa: Set[A]): List[A] = fa.toList | ||
|
||
override def reduceLeftOption[A](fa: Set[A])(f: (A, A) => A): Option[A] = | ||
fa.reduceLeftOption(f) | ||
|
||
override def find[A](fa: Set[A])(f: A => Boolean): Option[A] = fa.find(f) | ||
} | ||
|
||
implicit def catsStdShowForSet[A:Show]: Show[Set[A]] = new Show[Set[A]] { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :)