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
14 changes: 13 additions & 1 deletion src/main/scala/fpspeedrun/Eq.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
package fpspeedrun

trait Eq[T] {
def ===(x: T, y: T): Boolean
def ===(x: T, y: T): Boolean = ! !==(x, y)
def !==(x: T, y: T): Boolean = ! ===(x, y)
}

object Eq {

import syntax.eq.EqOps

implicit def listEq[T : Eq]: Eq[List[T]] = new Eq[List[T]] {
override def ===(x: List[T], y: List[T]): Boolean =
x.size == y.size && ( x zip y forall { case (a: T, b: T) => a === b } )
}

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

trait Ord[T] extends Eq[T]{
import fpspeedrun.Ord.{Compare, EQ}

trait Ord[T] extends Eq[T] {
override def ===(x: T, y: T): Boolean = compare(x, y) == EQ
def compare(x: T, y: T): 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
}

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

import syntax.ord.OrdOps

implicit def lexicographicalListOrd[T : Ord]: Ord[List[T]] = (x: List[T], y: List[T]) =>
x zip y find { case (a, b) => a !== b } match {
case Some((a, b)) => a compare b
case None => if (x.size < y.size) LT else if (x.size > y.size) GT else EQ
}

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

import fpspeedrun.Ord.{EQ, GT, LT}
import syntax.ord.OrdOps

object OrdInstances {

implicit def sizeFirstListOrd[T : Ord]: Ord[List[T]] = (x: List[T], y: List[T]) =>
if (x.size < y.size) LT
else if (x.size > y.size) GT
else x zip y find { case (a, b) => a !== b } match {
case Some((a, b)) => a compare b
case None => EQ
}

implicit def sizeOnlyListOrd[T : Ord]: Ord[List[T]] = (x: List[T], y: List[T]) =>
if (x.size < y.size) LT
else if (x.size > y.size) GT
else EQ

}
15 changes: 14 additions & 1 deletion src/main/scala/fpspeedrun/Ratio.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
package fpspeedrun

final case class Ratio()
import fpspeedrun.Ord.{EQ, GT, LT}

final case class Ratio(numerator: Int, denominator: Int)

object Ratio {

implicit val ratioOrd: Ord[Ratio] = (x: Ratio, y: Ratio) => {
val crossProductsDiff: Int = x.numerator * y.denominator - x.denominator * y.numerator

if (crossProductsDiff > 0) GT
else if (crossProductsDiff < 0) LT
else EQ
}

}
19 changes: 18 additions & 1 deletion src/main/scala/fpspeedrun/syntax.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
package fpspeedrun

import fpspeedrun.Ord.Compare

object syntax {
object eq{

object eq {

implicit class EqOps[T](val x: T) extends AnyVal{
def ===(y: T)(implicit eq: Eq[T]): Boolean = eq.===(x, y)
def !==(y: T)(implicit eq: Eq[T]): Boolean = eq.!==(x, y)
}

}

object ord {

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

}

}