Skip to content
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 Order instance for scala.Symbol #1395

Merged
merged 2 commits into from
Sep 28, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ possible:
* Csongor Kiss
* Dale Wijnand
* Daniel Spiewak
* Daniel Urban
* Dave Gurnell
* Dave Rostron
* David Allsopp
Expand Down
7 changes: 7 additions & 0 deletions kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class LawTests extends FunSuite with Discipline {
implicit val arbitraryBitSet: Arbitrary[BitSet] =
Arbitrary(arbitrary[List[Short]].map(ns => BitSet(ns.map(_ & 0xffff): _*)))

implicit val arbitrarySymbol: Arbitrary[Symbol] =
Arbitrary(arbitrary[String].map(s => Symbol(s)))

// this instance is not available in scalacheck 1.13.2.
// remove this once a newer version is available.
implicit val cogenBigInt: Cogen[BigInt] =
Expand All @@ -40,6 +43,9 @@ class LawTests extends FunSuite with Discipline {
implicit val cogenBigDecimal: Cogen[BigDecimal] =
Cogen[Double].contramap(_.toDouble)

implicit val cogenSymbol: Cogen[Symbol] =
Cogen[String].contramap(_.name)

{
// needed for Cogen[Map[...]]
implicit val ohe: Ordering[HasEq[Int]] = Ordering[Int].on(_.a)
Expand All @@ -64,6 +70,7 @@ class LawTests extends FunSuite with Discipline {
laws[OrderLaws, Unit].check(_.order)
laws[OrderLaws, Boolean].check(_.order)
laws[OrderLaws, String].check(_.order)
laws[OrderLaws, Symbol].check(_.order)
laws[OrderLaws, Byte].check(_.order)
laws[OrderLaws, Short].check(_.order)
laws[OrderLaws, Char].check(_.order)
Expand Down
1 change: 1 addition & 0 deletions kernel/src/main/scala/cats/kernel/instances/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ trait AllInstances
with ShortInstances
with StreamInstances
with StringInstances
with SymbolInstances
with TupleInstances
with UnitInstances
with VectorInstances
15 changes: 15 additions & 0 deletions kernel/src/main/scala/cats/kernel/instances/symbol.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cats.kernel
package instances

package object symbol extends SymbolInstances

trait SymbolInstances {
implicit val catsKernelStdOrderForSymbol: Order[Symbol] = new SymbolOrder
}

class SymbolOrder extends Order[Symbol] {
override def eqv(x: Symbol, y: Symbol): Boolean =
x eq y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use == here? I assume Symbol's equal method is correct and we don't need to worry here that eq is correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Symbols are interned ... might as well take advantage of that fact.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was my intention.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I know that eq is how it is implemented due to the interning, but equals already does this:
/~https://github.com/scala/scala/blob/2.12.x/src/library/scala/Symbol.scala#L31

so, this, to me, assumes the jit may not do the job, yet each reviewer of the code has to recall this fact about how Symbol instances are created.

That said, I'm happy to simply add a comment here to explain this so that the code is clearer to someone unfamiliar (I think Symbol is actually rather unused as a scala feature these days).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, comment added in 318e456.

def compare(x: Symbol, y: Symbol): Int =
if (x eq y) 0 else x.name compareTo y.name
}