Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 3 additions & 1 deletion src/main/scala/fpspeedrun/Eq.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fpspeedrun
import syntax.eq._

import fpspeedrun.syntax.eq._

import scala.annotation.tailrec

Expand Down Expand Up @@ -28,6 +29,7 @@ object Eq {
case y :: yt => x === y && go(xt, yt)
}
}

go
}
}
41 changes: 33 additions & 8 deletions src/main/scala/fpspeedrun/Ord.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
package fpspeedrun
import fpspeedrun.Ord.Compare

trait Ord[T] extends Eq[T]{
def compare(x: T, y: T): Compare
import fpspeedrun.syntax.ord._

import scala.annotation.tailrec

trait Ord[T] extends Eq[T] {
def compare(x: T, y: T): Ord.Compare
}

object Ord{
object Ord {

sealed trait Compare
object Compare{
case object LT //less than
case object EQ //equals to
case object GT //greater than

object Compare {

case object LT extends Ord.Compare //less than
case object EQ extends Ord.Compare //equals to
case object GT extends Ord.Compare //greater than
}

implicit def listOrd[A: Ord]: Ord[List[A]] = new Ord[List[A]] {
override def compare(x: List[A], y: List[A]): Compare = {
@tailrec def go(xs: List[A], ys: List[A]): Compare =
(xs, ys) match {
case (Nil, Nil) => Ord.Compare.EQ
case (Nil, _ :: _) => Ord.Compare.LT
case (_ :: _, Nil) => Ord.Compare.GT
case (xh :: xt, yh :: yt) => xh <> yh match {
case Compare.EQ => go(xt, yt)
case r => r
}
}

go(x, y)
}

override def ===(x: List[A], y: List[A]): Boolean = compare(x, y) == Ord.Compare.EQ
}
}
17 changes: 15 additions & 2 deletions src/main/scala/fpspeedrun/Ratio.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
package fpspeedrun

import syntax.eq._
import fpspeedrun.Ord.Compare

final case class Ratio(num: Int, den: Int)

object Ratio {
implicit val eq: Eq[Ratio] = (x, y) => x.num.toLong * y.den === x.den.toLong * y.num

implicit val ord: Ord[Ratio] = new Ord[Ratio] {
override def compare(x: Ratio, y: Ratio): Compare = {
x.num * y.den - y.num * x.den match {
case n if n < 0 => Ord.Compare.LT
case n if n > 0 => Ord.Compare.GT
case _ => Ord.Compare.EQ
}
}

override def ===(x: Ratio, y: Ratio): Boolean = compare(x, y) == Ord.Compare.EQ
}

implicit val eq: Eq[Ratio] = (x, y) => ord.===(x, y)
}

12 changes: 12 additions & 0 deletions src/main/scala/fpspeedrun/syntax/ord.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package fpspeedrun.syntax

import fpspeedrun.Ord
import fpspeedrun.Ord.Compare

object ord {

implicit class OrdOps[T](val x: T) extends AnyVal {
def <>(y: T)(implicit ord: Ord[T]): Compare = ord.compare(x, y)
}

}
26 changes: 26 additions & 0 deletions src/main/scala/test.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import fpspeedrun.Ratio
import fpspeedrun.syntax.eq._
import fpspeedrun.syntax.ord._


val r1 = Ratio(1, 2)
val r2 = Ratio(2, 4)
val r3 = Ratio(1, 3)
val r4 = Ratio(3, 6)
val r5 = Ratio(4, 8)

r1 === r2
r1 === r3

r1 <> r2
r1 <> r3

List(r1, r2) === List(r4, r3)
List(r1, r2) === List(r4, r5)

List(r1, r2) <> List(r4, r3)
List(r1, r2) <> List(r4, r5)
List(r3, r2) <> List(r4, r5)
List(r3) <> List(r4, r5)
List(r3, r2) <> List(r4)
List(r1, r2) <> List(r4)