Skip to content

Commit

Permalink
Add law tests and simple arbitrary and eq instances
Browse files Browse the repository at this point in the history
  • Loading branch information
Luka Jacobowitz committed Aug 8, 2018
1 parent 4bdf208 commit 13fd190
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
21 changes: 17 additions & 4 deletions core/src/main/scala/cats/data/Catenable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ sealed abstract class Catenable[+A] {
final def uncons: Option[(A, Catenable[A])] = {
var c: Catenable[A] = this
val rights = new collection.mutable.ArrayBuffer[Catenable[A]]
// scalastyle:off null
var result: Option[(A, Catenable[A])] = null
while (result eq null) {
c match {
Expand All @@ -36,6 +37,7 @@ sealed abstract class Catenable[+A] {
case Append(l, r) => c = l; rights += r
}
}
// scalastyle:on null
result
}

Expand Down Expand Up @@ -80,7 +82,7 @@ sealed abstract class Catenable[+A] {
result
}

/** collect `B` from this for which `f` is defined **/
/** Collect `B` from this for which `f` is defined */
final def collect[B](f: PartialFunction[A, B]): Catenable[B] = {
val predicate = f.lift
foldLeft(Catenable.empty: Catenable[B]) { (acc, a) =>
Expand Down Expand Up @@ -110,6 +112,7 @@ sealed abstract class Catenable[+A] {
private final def foreach(f: A => Unit): Unit = {
var c: Catenable[A] = this
val rights = new collection.mutable.ArrayBuffer[Catenable[A]]
// scalastyle:off null
while (c ne null) {
c match {
case Empty =>
Expand All @@ -128,6 +131,7 @@ sealed abstract class Catenable[+A] {
case Append(l, r) => c = l; rights += r
}
}
// scalastyle:on null
}


Expand All @@ -151,17 +155,21 @@ sealed abstract class Catenable[+A] {

def show[AA >: A](implicit AA: Show[AA]): String = {
val builder = new StringBuilder("Catenable(")
var first = true

foreach { a =>
builder ++= AA.show(a) + ", "; ()
if (first) { builder ++= AA.show(a); first = false }
else builder ++= ", " + AA.show(a)
()
}
builder += ')'
builder.result
}

override def toString = show(Show.show[A](_.toString))
override def toString: String = show(Show.show[A](_.toString))
}

object Catenable {
object Catenable extends CatenableInstances {
private[data] final case object Empty extends Catenable[Nothing] {
def isEmpty: Boolean = true
}
Expand Down Expand Up @@ -260,4 +268,9 @@ private[data] sealed abstract class CatenableInstances {
implicit def catsDataShowForCatenable[A](implicit A: Show[A]): Show[Catenable[A]] =
Show.show[Catenable[A]](_.show)

implicit def catsDataEqForCatenable[A](implicit A: Eq[A]): Eq[Catenable[A]] = new Eq[Catenable[A]] {
def eqv(x: Catenable[A], y: Catenable[A]): Boolean =
(x eq y) || x.toList === y.toList
}

}
11 changes: 11 additions & 0 deletions laws/src/main/scala/cats/laws/discipline/Arbitrary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,17 @@ object arbitrary extends ArbitraryInstances0 {
implicit def catsLawsCogenForAndThen[A, B](implicit F: Cogen[A => B]): Cogen[AndThen[A, B]] =
Cogen((seed, x) => F.perturb(seed, x))

implicit def catsLawsArbitraryForCatenable[A](implicit A: Arbitrary[A]): Arbitrary[Catenable[A]] =
Arbitrary(Gen.sized {
case 0 => Gen.const(Catenable.empty)
case 1 => A.arbitrary.map(Catenable.singleton)
case 2 => A.arbitrary.flatMap(a1 => A.arbitrary.flatMap(a2 =>
Catenable.append(Catenable.singleton(a1), Catenable.singleton(a2))))
case n => Catenable.fromSeq(Range.apply(0, n)).foldLeft(Gen.const(Catenable.empty: Catenable[A])) { (gen, _) =>
gen.flatMap(cat => A.arbitrary.map(a => cat :+ a))
}
})

}

private[discipline] sealed trait ArbitraryInstances0 {
Expand Down
25 changes: 25 additions & 0 deletions tests/src/test/scala/cats/tests/CatenableSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cats
package tests

import cats.data.Catenable
import cats.laws.discipline.{TraverseTests, AlternativeTests, MonadTests, SerializableTests}
import cats.laws.discipline.arbitrary._

class CatenableSuite extends CatsSuite {
checkAll("Catenable[Int]", AlternativeTests[Catenable].alternative[Int, Int, Int])
checkAll("Alternative[Catenable]", SerializableTests.serializable(Alternative[Catenable]))

checkAll("Catenable[Int] with Option", TraverseTests[Catenable].traverse[Int, Int, Int, Set[Int], Option, Option])
checkAll("Traverse[Catenable]", SerializableTests.serializable(Traverse[Catenable]))

checkAll("Catenable[Int]", MonadTests[Catenable].monad[Int, Int, Int])
checkAll("Monad[Catenable]", SerializableTests.serializable(Monad[Catenable]))

test("show"){
Catenable(1, 2, 3).show should === ("Catenable(1, 2, 3)")
(Catenable.empty: Catenable[Int]).show should === ("Catenable()")
forAll { l: Catenable[String] =>
l.show should === (l.toString)
}
}
}

0 comments on commit 13fd190

Please sign in to comment.