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

Adding FiniteDuration instances #2544

Merged
merged 9 commits into from
Oct 7, 2018
Merged
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
1 change: 1 addition & 0 deletions core/src/main/scala/cats/instances/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ trait AllInstancesBinCompat1

trait AllInstancesBinCompat2
extends DurationInstances
with FiniteDurationInstances
9 changes: 9 additions & 0 deletions core/src/main/scala/cats/instances/finiteDuration.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package cats
package instances

import scala.concurrent.duration.FiniteDuration

trait FiniteDurationInstances extends cats.kernel.instances.FiniteDurationInstances {
implicit val catsStdShowForFiniteDuration: Show[FiniteDuration] =
Show.fromToString[FiniteDuration]
}
1 change: 1 addition & 0 deletions core/src/main/scala/cats/instances/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ package object instances {
object eq extends EqInstances
object equiv extends EquivInstances
object float extends FloatInstances
object finiteDuration extends FiniteDurationInstances
object function extends FunctionInstances with FunctionInstancesBinCompat0
object future extends FutureInstances
object int extends IntInstances
Expand Down
33 changes: 32 additions & 1 deletion kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Arbitrary.arbitrary
import org.scalactic.anyvals.{ PosInt, PosZInt }
import org.scalatest.FunSuite

import scala.concurrent.duration.Duration
import scala.concurrent.duration.{ Duration, FiniteDuration }
import scala.collection.immutable.{BitSet, Queue}
import scala.util.Random

Expand Down Expand Up @@ -47,6 +47,20 @@ object KernelCheck {
Gen.choose(-n * 86400000000000L, n * 86400000000000L).map(Duration(_, NANOSECONDS))))
}

implicit val arbitraryFiniteDuration: Arbitrary[FiniteDuration] = {
// max range is +/- 292 years, but we give ourselves some extra headroom
// to ensure that we can add these things up. they crash on overflow.
val n = (292L * 365) / 50
Arbitrary(Gen.oneOf(
Gen.choose(-n, n).map(FiniteDuration(_, DAYS)),
Gen.choose(-n * 24L, n * 24L).map(FiniteDuration(_, HOURS)),
Gen.choose(-n * 1440L, n * 1440L).map(FiniteDuration(_, MINUTES)),
Gen.choose(-n * 86400L, n * 86400L).map(FiniteDuration(_, SECONDS)),
Gen.choose(-n * 86400000L, n * 86400000L).map(FiniteDuration(_, MILLISECONDS)),
Gen.choose(-n * 86400000000L, n * 86400000000L).map(FiniteDuration(_, MICROSECONDS)),
Gen.choose(-n * 86400000000000L, n * 86400000000000L).map(FiniteDuration(_, NANOSECONDS))))
}

// this instance is not available in scalacheck 1.13.2.
// remove this once a newer version is available.
implicit val cogenBigInt: Cogen[BigInt] =
Expand Down Expand Up @@ -78,6 +92,19 @@ object KernelCheck {
case NANOSECONDS => 6128745701389500153L
})
}

implicit val cogenFiniteDuration: Cogen[FiniteDuration] =
Cogen[Long].contramap { d =>
d.length * (d.unit match {
case DAYS => -6307593037248227856L
case HOURS => -3527447467459552709L
case MINUTES => 5955657079535371609L
case SECONDS => 5314272869665647192L
case MILLISECONDS => -2025740217814855607L
case MICROSECONDS => -2965853209268633779L
case NANOSECONDS => 6128745701389500153L
})
}
}

class Tests extends FunSuite with Discipline {
Expand Down Expand Up @@ -132,6 +159,7 @@ class Tests extends FunSuite with Discipline {
checkAll("PartialOrder[BitSet]", PartialOrderTests[BitSet].partialOrder)
checkAll("Order[BigInt]", OrderTests[BigInt].order)
checkAll("Order[Duration]", OrderTests[Duration].order)
checkAll("Order[FiniteDuration]", OrderTests[FiniteDuration].order)
checkAll("Order[UUID]", OrderTests[UUID].order)
checkAll("Order[List[Int]]", OrderTests[List[Int]] .order)
checkAll("Order[Option[String]]", OrderTests[Option[String]].order)
Expand Down Expand Up @@ -187,6 +215,8 @@ class Tests extends FunSuite with Discipline {
checkAll("CommutativeGroup[BigInt]", SerializableTests.serializable(CommutativeGroup[BigInt]))
checkAll("CommutativeGroup[Duration]", CommutativeGroupTests[Duration].commutativeGroup)
checkAll("CommutativeGroup[Duration]", SerializableTests.serializable(CommutativeGroup[Duration]))
checkAll("CommutativeGroup[FiniteDuration]", CommutativeGroupTests[FiniteDuration].commutativeGroup)
checkAll("CommutativeGroup[FiniteDuration]", SerializableTests.serializable(CommutativeGroup[FiniteDuration]))


checkAll("Hash[Unit]" , HashTests[Unit].hash)
Expand All @@ -198,6 +228,7 @@ class Tests extends FunSuite with Discipline {
checkAll("Hash[Char]" , HashTests[Char].hash)
checkAll("Hash[Int]" , HashTests[Int].hash)
checkAll("Hash[Duration]", HashTests[Duration].hash)
checkAll("Hash[FiniteDuration]", HashTests[FiniteDuration].hash)

// NOTE: Do not test for Float/Double/Long. These types'
// `##` is different from `hashCode`. See [[scala.runtime.Statics.anyHash]].
Expand Down
5 changes: 4 additions & 1 deletion kernel/src/main/scala/cats/kernel/instances/all.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package cats.kernel
package instances

package object all extends AllInstances
package object all extends AllInstances with AllInstancesBinCompat0

trait AllInstances
extends BigDecimalInstances
Expand Down Expand Up @@ -34,3 +34,6 @@ trait AllInstances
with UnitInstances
with UUIDInstances
with VectorInstances


trait AllInstancesBinCompat0 extends FiniteDurationInstances
32 changes: 32 additions & 0 deletions kernel/src/main/scala/cats/kernel/instances/finiteDuration.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cats.kernel
package instances

import scala.concurrent.duration.{ Duration, FiniteDuration }


trait FiniteDurationInstances {
implicit val catsKernelStdOrderForFiniteDuration: Order[FiniteDuration] with Hash[FiniteDuration] = new FiniteDurationOrder
implicit val catsKernelStdGroupForFiniteDuration: CommutativeGroup[FiniteDuration] = new FiniteDurationGroup
}
class FiniteDurationOrder extends Order[FiniteDuration] with Hash[FiniteDuration] {
def hash(x: FiniteDuration): Int = x.hashCode()

def compare(x: FiniteDuration, y: FiniteDuration): Int = x compare y

override def eqv(x: FiniteDuration, y: FiniteDuration): Boolean = x == y
override def neqv(x: FiniteDuration, y: FiniteDuration): Boolean = x != y
override def gt(x: FiniteDuration, y: FiniteDuration): Boolean = x > y
override def gteqv(x: FiniteDuration, y: FiniteDuration): Boolean = x >= y
override def lt(x: FiniteDuration, y: FiniteDuration): Boolean = x < y
override def lteqv(x: FiniteDuration, y: FiniteDuration): Boolean = x <= y

override def min(x: FiniteDuration, y: FiniteDuration): FiniteDuration = x min y
override def max(x: FiniteDuration, y: FiniteDuration): FiniteDuration = x max y
}

class FiniteDurationGroup extends CommutativeGroup[FiniteDuration] {
def empty: FiniteDuration = Duration.Zero
def inverse(x: FiniteDuration): FiniteDuration = -x
def combine(x: FiniteDuration, y: FiniteDuration): FiniteDuration = x + y
override def remove(x: FiniteDuration, y: FiniteDuration): FiniteDuration = x - y
}
15 changes: 15 additions & 0 deletions tests/src/test/scala/cats/tests/FiniteDurationSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cats
package tests

import cats.laws.discipline.SerializableTests

import scala.concurrent.duration.{ DurationInt, FiniteDuration }

class FiniteDurationSuite extends CatsSuite {
checkAll("Show[FiniteDuration]", SerializableTests.serializable(Show[FiniteDuration]))

test("show works for FiniteDuration"){
Show[FiniteDuration].show(23.minutes) should ===("23 minutes")
Show[FiniteDuration].show(10.seconds) should === ("10 seconds")
}
}