-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Set up Machinist, use macros for Eq through Order syntax.
This commit adds cats-macros, upon which cats depends. Right now, the only macros being used are Machinist's operator macros, which are configured in cats.macros.Ops. The punchline of doing this is that: def xyz[A: Eq](x: A, y: A): Boolean = x === y is now exactly the same as: def xyz[A](x: A, y: A)(implicit A: Eq[A]): Boolean = A.eqv(x, y) i.e. the syntax implicit conversions are completely erased. This eliminates the performance penalty that syntax normally implies. It also means the syntax classes don't need to be value classes (or specialized) since they are not used at runtime.
- Loading branch information
Showing
5 changed files
with
55 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,14 @@ | ||
package cats | ||
package syntax | ||
|
||
import cats.macros.Ops | ||
import scala.language.experimental.macros | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
trait EqSyntax { | ||
// TODO: use simulacrum instances eventually | ||
implicit def eqSyntax[A: Eq](a: A) = | ||
new EqOps[A](a) | ||
implicit def eqSyntax[A: Eq](a: A) = new EqOps[A](a) | ||
} | ||
|
||
class EqOps[A](lhs: A)(implicit A: Eq[A]) { | ||
def ===(rhs: A): Boolean = A.eqv(lhs, rhs) | ||
def =!=(rhs: A): Boolean = A.neqv(lhs, rhs) | ||
def ===(rhs: A): Boolean = macro Ops.binop[A, Boolean] | ||
def =!=(rhs: A): Boolean = macro Ops.binop[A, Boolean] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,15 @@ | ||
package cats | ||
package syntax | ||
|
||
import cats.macros.Ops | ||
import scala.language.experimental.macros | ||
|
||
trait OrderSyntax { | ||
// TODO: use simulacrum instances eventually | ||
implicit def orderSyntax[A: Order](a: A) = | ||
new OrderOps[A](a) | ||
implicit def orderSyntax[A: Order](a: A) = new OrderOps[A](a) | ||
} | ||
|
||
class OrderOps[A](lhs: A)(implicit A: Order[A]) { | ||
def compare(rhs: A): Int = A.compare(lhs, rhs) | ||
def min(rhs: A): A = A.min(lhs, rhs) | ||
def max(rhs: A): A = A.max(lhs, rhs) | ||
def compare(rhs: A): Int = macro Ops.binop[A, Int] | ||
def min(rhs: A): A = macro Ops.binop[A, A] | ||
def max(rhs: A): A = macro Ops.binop[A, A] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,21 @@ | ||
package cats | ||
package syntax | ||
|
||
import cats.macros.Ops | ||
import scala.language.experimental.macros | ||
|
||
trait PartialOrderSyntax { | ||
// TODO: use simulacrum instances eventually | ||
implicit def partialOrderSyntax[A: PartialOrder](a: A) = | ||
new PartialOrderOps[A](a) | ||
implicit def partialOrderSyntax[A: PartialOrder](a: A) = new PartialOrderOps[A](a) | ||
} | ||
|
||
class PartialOrderOps[A](lhs: A)(implicit A: PartialOrder[A]) { | ||
def >(rhs: A): Boolean = A.gt(lhs, rhs) | ||
def >=(rhs: A): Boolean = A.gteqv(lhs, rhs) | ||
def <(rhs: A): Boolean = A.lt(lhs, rhs) | ||
def <=(rhs: A): Boolean = A.lteqv(lhs, rhs) | ||
def >(rhs: A): Boolean = macro Ops.binop[A, Boolean] | ||
def >=(rhs: A): Boolean = macro Ops.binop[A, Boolean] | ||
def <(rhs: A): Boolean = macro Ops.binop[A, Boolean] | ||
def <=(rhs: A): Boolean = macro Ops.binop[A, Boolean] | ||
|
||
def partialCompare(rhs: A): Double = A.partialCompare(lhs, rhs) | ||
def tryCompare(rhs: A): Option[Int] = A.tryCompare(lhs, rhs) | ||
def pmin(rhs: A): Option[A] = A.pmin(lhs, rhs) | ||
def pmax(rhs: A): Option[A] = A.pmax(lhs, rhs) | ||
def partialCompare(rhs: A): Double = macro Ops.binop[A, Double] | ||
def tryCompare(rhs: A): Option[Int] = macro Ops.binop[A, Option[Int]] | ||
def pmin(rhs: A): Option[A] = macro Ops.binop[A, Option[A]] | ||
def pmax(rhs: A): Option[A] = macro Ops.binop[A, Option[A]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package cats.macros | ||
|
||
object Ops extends machinist.Ops { | ||
|
||
def uesc(c: Char): String = "$u%04X".format(c.toInt) | ||
|
||
val operatorNames: Map[String, String] = | ||
Map( | ||
("$eq$eq$eq", "eqv"), | ||
("$eq$bang$eq", "neqv"), | ||
("$greater", "gt"), | ||
("$greater$eq", "gteqv"), | ||
("$less", "lt"), | ||
("$less$eq", "lteqv"), | ||
("$bar$plus$bar", "combine"), | ||
("$bar$minus$bar", "remove") | ||
) | ||
} |
1 comment
on commit ce14308
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.
Nice. 👍
we could add this to the sbt file: