cats.kernel.laws.discipline.MonoidTests Scala Examples

The following examples show how to use cats.kernel.laws.discipline.MonoidTests. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: LawTests.scala    From paiges   with Apache License 2.0 5 votes vote down vote up
package org.typelevel.paiges

import cats.Semigroupal
import cats.Contravariant
import cats.kernel.{Eq, Monoid}
import cats.laws.discipline.{ContravariantTests, DeferTests, ExhaustiveCheck, SemigroupalTests, SerializableTests}
import cats.kernel.laws.discipline.MonoidTests
import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive

import org.typelevel.discipline.scalatest.FunSuiteDiscipline
import org.scalacheck.Arbitrary
import org.scalactic.anyvals.{PosInt, PosZDouble, PosZInt}
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.prop.Configuration

class LawTests extends LawChecking with CatsDocument {
  import org.typelevel.paiges.Generators._
  import org.typelevel.paiges.instances._

  implicit val docEq: Eq[Doc] =
    Eq.instance((x: Doc, y: Doc) => PaigesTest.docEquiv.equiv(x, y))

  implicit def monoidTests[A: Eq: Arbitrary: Monoid] = MonoidTests[A]

  implicit def arbitraryForDocument[A]: Arbitrary[Document[A]] =
    Arbitrary(Document.useToString[A])

  implicit def eqForDocument[A: ExhaustiveCheck]: Eq[Document[A]] =
    Eq.by[Document[A], A => Doc](inst => (a: A) => inst.document(a))

  implicit val eqBool: Eq[Boolean] =
    Eq.instance[Boolean](_ == _)

  checkAll("Monoid[Doc]", MonoidTests[Doc].monoid)
  checkAll("Monoid[Style]", MonoidTests[Style].monoid)

  checkAll("Contravariant[Document]", ContravariantTests[Document].contravariant[Boolean, Boolean, Boolean])
  checkAll("Contravariant[Document]", SerializableTests.serializable(Contravariant[Document]))
  checkAll("Defer[Document]", DeferTests[Document].defer[Boolean])

  {
    implicit val semigroupalDocument: Semigroupal[Document] =
      CatsDocument.semigroupalDocument(Doc.char(','))
    checkAll("Semigroupal[Document]", SemigroupalTests[Document].semigroupal[Boolean, Boolean, Boolean])
    checkAll("Semigroupal[Document]", SerializableTests.serializable(Semigroupal[Document]))
  }
}

abstract class LawChecking extends AnyFunSuite with Configuration with FunSuiteDiscipline {

  lazy val checkConfiguration: PropertyCheckConfiguration =
    PropertyCheckConfiguration(
      minSuccessful = if (Platform.isJvm) PosInt(50) else PosInt(5),
      maxDiscardedFactor = if (Platform.isJvm) PosZDouble(5.0) else PosZDouble(50.0),
      minSize = PosZInt(0),
      sizeRange = if (Platform.isJvm) PosZInt(10) else PosZInt(5),
      workers = PosInt(1)
    )

  // The scalacheck defaults 'sizeRange' (100) is too high for Scala-js, so we reduce to 10.
  // We also set `minSuccessful` to 100 unconditionally.
  implicit override val generatorDrivenConfig: PropertyCheckConfiguration =
    if (Platform.isJvm) PropertyCheckConfiguration(sizeRange = 100, minSuccessful = 100)
    else PropertyCheckConfiguration(sizeRange = 10, minSuccessful = 100)
} 
Example 2
Source File: RerunnableSuite.scala    From catbird   with Apache License 2.0 5 votes vote down vote up
package io.catbird.util

import cats.instances.either._
import cats.instances.int._
import cats.instances.tuple._
import cats.instances.unit._
import cats.kernel.laws.discipline.MonoidTests
import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
import cats.{ Comonad, Eq }
import com.twitter.conversions.DurationOps._
import org.scalacheck.Arbitrary

class RerunnableSuite extends CatbirdSuite with ArbitraryInstances with EqInstances {
  implicit def rerunnableEq[A](implicit A: Eq[A]): Eq[Rerunnable[A]] =
    Rerunnable.rerunnableEqWithFailure[A](1.second)
  implicit val rerunnableComonad: Comonad[Rerunnable] =
    Rerunnable.rerunnableComonad(1.second)
  implicit val rerunnableParEqInt: Eq[Rerunnable.Par[Int]] =
    Rerunnable.rerunnableParEqWithFailure(1.second)
  implicit val rerunnableParEqInt3: Eq[Rerunnable.Par[(Int, Int, Int)]] =
    Rerunnable.rerunnableParEqWithFailure(1.second)
  implicit def rerunnableParArbitrary[A](implicit A: Arbitrary[A]): Arbitrary[Rerunnable.Par[A]] =
    Arbitrary(A.arbitrary.map(value => Rerunnable.Par(Rerunnable.const(value))))

  checkAll("Rerunnable[Int]", MonadErrorTests[Rerunnable, Throwable].monadError[Int, Int, Int])
  checkAll("Rerunnable[Int]", ComonadTests[Rerunnable].comonad[Int, Int, Int])
  checkAll("Rerunnable[Int]", FunctorTests[Rerunnable](rerunnableComonad).functor[Int, Int, Int])
  checkAll("Rerunnable[Int]", MonoidTests[Rerunnable[Int]].monoid)
  checkAll("Rerunnable[Int]", ParallelTests[Rerunnable, Rerunnable.Par].parallel[Int, Int])
  checkAll("Rerunnable.Par[Int]", CommutativeApplicativeTests[Rerunnable.Par].commutativeApplicative[Int, Int, Int])
} 
Example 3
Source File: var.scala    From catbird   with Apache License 2.0 5 votes vote down vote up
package io.catbird.util

import cats.instances.int._
import cats.instances.tuple._
import cats.kernel.laws.discipline.{ MonoidTests, SemigroupTests }
import cats.laws.discipline._
import cats.{ Comonad, Eq }
import com.twitter.util.Var

class VarSuite extends CatbirdSuite with VarInstances with ArbitraryInstances {
  implicit val eqVarInt: Eq[Var[Int]] = varEq
  implicit val eqVarVarInt: Eq[Var[Var[Int]]] = varEq
  implicit val eqVarVarVarInt: Eq[Var[Var[Var[Int]]]] = varEq
  implicit val eqVarInt3: Eq[Var[(Int, Int, Int)]] = varEq[(Int, Int, Int)]
  implicit val comonad: Comonad[Var] = varComonad

  checkAll("Var[Int]", MonadTests[Var].stackUnsafeMonad[Int, Int, Int])
  checkAll("Var[Int]", ComonadTests[Var].comonad[Int, Int, Int])
  checkAll("Var[Int]", SemigroupTests[Var[Int]](twitterVarSemigroup[Int]).semigroup)
  checkAll("Var[Int]", MonoidTests[Var[Int]].monoid)
} 
Example 4
Source File: try.scala    From catbird   with Apache License 2.0 5 votes vote down vote up
package io.catbird.util

import cats.instances.either._
import cats.instances.int._
import cats.instances.option._
import cats.instances.tuple._
import cats.instances.unit._
import cats.kernel.laws.discipline.{ MonoidTests, SemigroupTests }
import cats.laws.discipline.arbitrary._
import cats.laws.discipline.{ MonadErrorTests, TraverseTests }
import com.twitter.util.{ Return, Throw, Try }
import org.scalatest.propspec.AnyPropSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks

trait TryTest extends ArbitraryInstances with EqInstances with TryInstances

class TrySuite extends CatbirdSuite with TryTest {
  checkAll("Try[Int]", MonadErrorTests[Try, Throwable].monadError[Int, Int, Int])
  checkAll("Try[Int]", TraverseTests[Try].traverse[Int, Int, Int, Int, Option, Option])
  checkAll("Try[Int]", SemigroupTests[Try[Int]](twitterTrySemigroup[Int]).semigroup)
  checkAll("Try[Int]", MonoidTests[Try[Int]].monoid)
}

class TrySpec extends AnyPropSpec with ScalaCheckPropertyChecks with TryTest {
  property("Equality for Try should use universal equality for Throw") {
    case class SomeError(message: String) extends Exception(message)

    forAll((s: String) => assert(twitterTryEq[Int].eqv(Throw(SomeError(s)), Throw(SomeError(s)))))
  }

  property("Equality for Try should never mix up Return and Throw") {
    forAll((i: Int) => assert(!twitterTryEq[Int].eqv(Throw(new Exception), Return(i))))
  }
} 
Example 5
Source File: future.scala    From catbird   with Apache License 2.0 5 votes vote down vote up
package io.catbird.util

import cats.instances.either._
import cats.instances.int._
import cats.instances.tuple._
import cats.instances.unit._
import cats.kernel.laws.discipline.{ MonoidTests, SemigroupTests }
import cats.laws.discipline._
import cats.laws.discipline.arbitrary._
import cats.{ Comonad, Eq }
import com.twitter.conversions.DurationOps._
import com.twitter.util.Future
import org.scalacheck.Arbitrary

class FutureSuite extends CatbirdSuite with FutureInstances with ArbitraryInstances with EqInstances {
  implicit val eqFutureInt: Eq[Future[Int]] = futureEqWithFailure(1.second)
  implicit val eqFutureFutureInt: Eq[Future[Future[Int]]] = futureEqWithFailure(1.second)
  implicit val eqFutureFutureFutureInt: Eq[Future[Future[Future[Int]]]] = futureEqWithFailure(1.second)
  implicit val eqFutureInt3: Eq[Future[(Int, Int, Int)]] = futureEqWithFailure(1.second)
  implicit val eqFutureEitherUnit: Eq[Future[Either[Throwable, Unit]]] = futureEqWithFailure(1.second)
  implicit val eqFutureEitherInt: Eq[Future[Either[Throwable, Int]]] = futureEqWithFailure(1.second)
  implicit val comonad: Comonad[Future] = futureComonad(1.second)
  implicit val eqFutureParInt: Eq[FuturePar[Int]] = futureParEqWithFailure(1.second)
  implicit val eqFutureParInt3: Eq[FuturePar[(Int, Int, Int)]] = futureParEqWithFailure(1.second)
  implicit def arbFuturePar[A](implicit A: Arbitrary[A]): Arbitrary[FuturePar[A]] =
    Arbitrary(A.arbitrary.map(value => FuturePar(Future.value(value))))

  checkAll("Future[Int]", MonadErrorTests[Future, Throwable].monadError[Int, Int, Int])
  checkAll("Future[Int]", ComonadTests[Future].comonad[Int, Int, Int])
  checkAll("Future[Int]", FunctorTests[Future](comonad).functor[Int, Int, Int])
  checkAll("Future[Int]", SemigroupTests[Future[Int]](twitterFutureSemigroup[Int]).semigroup)
  checkAll("Future[Int]", MonoidTests[Future[Int]].monoid)
  checkAll("Future[Int]", ParallelTests[Future, FuturePar].parallel[Int, Int])
  checkAll("FuturePar[Int]", CommutativeApplicativeTests[FuturePar].commutativeApplicative[Int, Int, Int])
} 
Example 6
Source File: RadixTreeLawsCheck.scala    From radixtree   with Apache License 2.0 5 votes vote down vote up
package com.rklaehn.radixtree

import algebra.instances.all._
import org.scalacheck.Arbitrary
import org.scalatest.FunSuite
import org.typelevel.discipline.scalatest.Discipline
import Instances._
import algebra.laws.RingLaws
import cats.kernel.laws.discipline.MonoidTests

class RadixTreeLawsCheck extends FunSuite with Discipline {

  implicit def arbRadixTree[K: Arbitrary : RadixTree.Key, V: Arbitrary]: Arbitrary[RadixTree[K, V]] = Arbitrary {
    for {
      kvs ← Arbitrary.arbitrary[List[(K, V)]]
    } yield
    RadixTree(kvs: _*)
  }

  checkAll("MonoidTests[RadixTree[String, String]].monoid", MonoidTests[RadixTree[String, String]].monoid)
  checkAll("MonoidTests[RadixTree[Array[Byte], Array[Byte]]].monoid", MonoidTests[RadixTree[Array[Byte], Array[Byte]]].monoid)
  checkAll("RingLaws[RadixTree[String, Byte]].additiveMonoid", RingLaws[RadixTree[String, Short]].additiveMonoid)
  checkAll("RingLaws[RadixTree[Array[Byte], Int]].additiveMonoid", RingLaws[RadixTree[String, Int]].additiveMonoid)
} 
Example 7
Source File: DocumentInstancesSpec.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
package rocks.muki.graphql.instances

import cats._
import cats.kernel.laws.discipline.MonoidTests
import cats.tests.CatsSuite
import org.scalacheck.{Arbitrary, Gen}
import rocks.muki.graphql.codegen.style.sangria.TestSchema
import sangria.ast.Document

class DocumentInstancesSpec extends CatsSuite {
  implicit private val arbDocument: Arbitrary[Document] =
    Arbitrary(
      Gen.oneOf(
        Document(Vector.empty),
        Document.emptyStub,
        Document(TestSchema.StarWarsSchema.toAst.definitions.take(3))
      )
    )
  implicit private val eqDocument: Eq[Document] =
    Eq.fromUniversalEquals[Document]

  checkAll("Monoid[sangria.ast.Document]", MonoidTests[Document].monoid)
} 
Example 8
Source File: LoggerMonoidSpec.scala    From odin   with Apache License 2.0 5 votes vote down vote up
package io.odin.loggers

import java.util.UUID

import cats.data.WriterT
import cats.effect.{Clock, IO, Timer}
import cats.instances.list._
import cats.instances.tuple._
import cats.instances.unit._
import cats.instances.uuid._
import cats.kernel.laws.discipline.MonoidTests
import cats.syntax.all._
import io.odin.{Level, Logger, LoggerMessage, OdinSpec}
import org.scalacheck.{Arbitrary, Gen}

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

class LoggerMonoidSpec extends OdinSpec {
  type F[A] = WriterT[IO, List[(UUID, LoggerMessage)], A]

  checkAll("Logger", MonoidTests[Logger[F]].monoid)

  it should "(logger1 |+| logger2).log <-> (logger1.log |+| logger2.log)" in {
    forAll { (uuid1: UUID, uuid2: UUID, msg: LoggerMessage) =>
      val logger1: Logger[F] = NamedLogger(uuid1)
      val logger2: Logger[F] = NamedLogger(uuid2)
      val a = (logger1 |+| logger2).log(msg)
      val b = logger1.log(msg) |+| logger2.log(msg)
      a.written.unsafeRunSync() shouldBe b.written.unsafeRunSync()
    }
  }

  it should "(logger1 |+| logger2).log(list) <-> (logger1.log |+| logger2.log(list))" in {
    forAll { (uuid1: UUID, uuid2: UUID, msg: List[LoggerMessage]) =>
      val logger1: Logger[F] = NamedLogger(uuid1)
      val logger2: Logger[F] = NamedLogger(uuid2)
      val a = (logger1 |+| logger2).log(msg)
      val b = logger1.log(msg) |+| logger2.log(msg)
      a.written.unsafeRunSync() shouldBe b.written.unsafeRunSync()
    }
  }

  it should "set minimal level for underlying loggers" in {
    forAll { (uuid1: UUID, uuid2: UUID, level: Level, msg: List[LoggerMessage]) =>
      val logger1: Logger[F] = NamedLogger(uuid1)
      val logger2: Logger[F] = NamedLogger(uuid2)
      val a = (logger1 |+| logger2).withMinimalLevel(level).log(msg)
      val b = (logger1.withMinimalLevel(level) |+| logger2.withMinimalLevel(level)).log(msg)
      a.written.unsafeRunSync() shouldBe b.written.unsafeRunSync()
    }
  }

  case class NamedLogger(loggerId: UUID) extends DefaultLogger[F] {
    def log(msg: LoggerMessage): F[Unit] = WriterT.tell(List(loggerId -> msg))
  }

  implicit def timer: Timer[IO] = new Timer[IO] {
    def clock: Clock[IO] = new Clock[IO] {
      def realTime(unit: TimeUnit): IO[Long] = IO.pure(0)

      def monotonic(unit: TimeUnit): IO[Long] = IO.pure(0)
    }

    def sleep(duration: FiniteDuration): IO[Unit] = ???
  }

  implicit def arbitraryWriterLogger: Arbitrary[Logger[F]] = Arbitrary(
    Gen.uuid.map(NamedLogger)
  )
} 
Example 9
Source File: monoid.scala    From kittens   with Apache License 2.0 5 votes vote down vote up
package cats.derived

import cats.{Eq, Monoid}
import cats.instances.all._
import cats.kernel.laws.discipline.{MonoidTests, SerializableTests}
import org.scalacheck.Arbitrary

class MonoidSuite extends KittensSuite {
  import MonoidSuite._
  import TestDefns._
  import TestEqInstances._

  def testMonoid(context: String)(
    implicit foo: Monoid[Foo],
    recursive: Monoid[Recursive],
    interleaved: Monoid[Interleaved[Int]],
    box: Monoid[Box[Mul]]
  ): Unit = {
    checkAll(s"$context.Monoid[Foo]", MonoidTests[Foo].monoid)
    checkAll(s"$context.Monoid[Recursive]", MonoidTests[Recursive].monoid)
    checkAll(s"$context.Monoid[Interleaved[Int]]", MonoidTests[Interleaved[Int]].monoid)
    checkAll(s"$context.Monoid[Box[Mul]]", MonoidTests[Box[Mul]].monoid)
    checkAll(s"$context.Monoid is Serializable", SerializableTests.serializable(Monoid[Interleaved[Int]]))

    test(s"$context.Monoid respects existing instances") {
      assert(box.empty == Box(Mul(1)))
      assert(box.combine(Box(Mul(5)), Box(Mul(5))) == Box(Mul(25)))
    }
  }

  {
    import auto.monoid._
    testMonoid("auto")
  }

  {
    import cached.monoid._
    testMonoid("cached")
  }

  {
    import semiInstances._
    testMonoid("semiauto")
  }
}

object MonoidSuite {
  import TestDefns._

  object semiInstances {
    implicit val foo: Monoid[Foo] = semiauto.monoid
    implicit lazy val recursive: Monoid[Recursive] = semiauto.monoid
    implicit val interleaved: Monoid[Interleaved[Int]] = semiauto.monoid
    implicit val box: Monoid[Box[Mul]] = semiauto.monoid
  }

  final case class Mul(value: Int)
  object Mul {

    implicit val eqv: Eq[Mul] =
      Eq.fromUniversalEquals

    implicit val arbitrary: Arbitrary[Mul] =
      Arbitrary(Arbitrary.arbitrary[Int].map(apply))

    implicit val monoid: Monoid[Mul] = new Monoid[Mul] {
      val empty = Mul(1)
      def combine(x: Mul, y: Mul) = Mul(x.value * y.value)
    }
  }
} 
Example 10
Source File: LastOptionTest.scala    From newts   with Apache License 2.0 5 votes vote down vote up
package newts

import cats.Show
import cats.kernel.laws.discipline.{MonoidTests, EqTests}
import cats.laws.discipline.{AlternativeTests, TraverseTests}

class LastOptionTest extends NewtsSuite {

  checkAll("LastOption[Int]", AlternativeTests[LastOption].monoidK[Int])
  checkAll("LastOption[Int]", MonoidTests[LastOption[Int]].monoid)
  checkAll("LastOption[Int]", EqTests[LastOption[Int]].eqv)
  checkAll("LastOption[Int]", TraverseTests[LastOption].traverse[Int, Int, Int, Int, Option, Option])

  test("combine"){
    1.some.asLastOption |+| 2.some.asLastOption shouldEqual LastOption(Some(2))
    1.some.asLastOption |+| none.asLastOption   shouldEqual LastOption(Some(1))
  }

  class ShowTest
  implicit val showTest = new Show[ShowTest]() {
    override def show(f: ShowTest): String = "test show method"
  }

  test("show") {
    LastOption(Some(1)).show shouldEqual "LastOption(Some(1))"
    LastOption(Some("Hello")).show shouldEqual "LastOption(Some(Hello))"
    LastOption(Option.empty[String]).show shouldEqual "LastOption(None)"
    new ShowTest().some.asLastOption.show shouldEqual "LastOption(Some(test show method))"
  }
} 
Example 11
Source File: AllTest.scala    From newts   with Apache License 2.0 5 votes vote down vote up
package newts

import cats.kernel.laws.discipline.{MonoidTests, EqTests}

class AllTest extends NewtsSuite {

  checkAll("All", MonoidTests[All].monoid)
  checkAll("All", EqTests[All].eqv)

  test("combine"){
    true.asAll   |+| true.asAll   shouldEqual true.asAll
    All(true)    |+| All(false) shouldEqual All(false)
    All(false)   |+| All(true)  shouldEqual All(false)
    All(false)   |+| All(false) shouldEqual All(false)
  }

  test("show") {
    All(true).show shouldEqual "All(true)"
    All(false).show shouldEqual "All(false)"
  }
} 
Example 12
Source File: AnyTest.scala    From newts   with Apache License 2.0 5 votes vote down vote up
package newts

import cats.kernel.laws.discipline.{MonoidTests, EqTests}

class AnyTest extends NewtsSuite {

  checkAll("Any", MonoidTests[Any].monoid)
  checkAll("Any", EqTests[Any].eqv)

  test("combine"){
    true.asAny   |+| true.asAny shouldEqual true.asAny
    Any(true)    |+| Any(false) shouldEqual Any(true)
    Any(false)   |+| Any(true)  shouldEqual Any(true)
    Any(false)   |+| Any(false) shouldEqual Any(false)
  }

  test("show") {
    Any(true).show  shouldEqual "Any(true)"
    Any(false).show shouldEqual "Any(false)"
  }
} 
Example 13
Source File: DualTest.scala    From newts   with Apache License 2.0 5 votes vote down vote up
package newts

import cats.Id
import cats.data.NonEmptyList
import cats.kernel.laws.discipline.{EqTests, MonoidTests, SemigroupTests}
import cats.laws.discipline.{DistributiveTests, MonadTests, TraverseTests}
import cats.laws.discipline.arbitrary._
import fixtures.ShowTestClass

class DualTest extends NewtsSuite {

  checkAll("Dual[NonEmptyList[Int]]", SemigroupTests[Dual[NonEmptyList[Int]]].semigroup)
  checkAll("Dual[List[Int]]"        , MonoidTests[Dual[List[Int]]].monoid)
  checkAll("Dual[Int]"              , EqTests[Dual[Int]].eqv)
  checkAll("Dual[Int]"              , MonadTests[Dual].monad[Int, Int, Int])
  checkAll("Dual[Int]"              , TraverseTests[Dual].traverse[Int, Int, Int, Int, Option, Option])
  checkAll("Dual[Int]"              , DistributiveTests[Dual].distributive[Int, Int, Int, Option, Id])

  test("combine"){
    val xs = NonEmptyList.of(1,2)
    val ys = NonEmptyList.of(3,4)

    xs.asDual |+| ys.asDual shouldEqual (ys |+| xs).asDual
  }

  test("show") {
    Dual("aString").show shouldEqual "Dual(aString)"
    Dual(42).show shouldEqual "Dual(42)"
    Dual(new ShowTestClass).show shouldEqual s"Dual(${ShowTestClass.show})"
  }

  test("dual of first is last"){
    val xs = NonEmptyList(1, List(2,3,4,5))

    xs.reduceMap(_.asFirst.asDual).getDual.getFirst shouldEqual 5
  }
} 
Example 14
Source File: FirstOptionTest.scala    From newts   with Apache License 2.0 5 votes vote down vote up
package newts

import cats.kernel.laws.discipline.{MonoidTests, EqTests}
import cats.laws.discipline.{AlternativeTests, TraverseTests}
import fixtures.ShowTestClass

class FirstOptionTest extends NewtsSuite {

  checkAll("FirstOption[Int]", AlternativeTests[FirstOption].monoidK[Int])
  checkAll("FirstOption[Int]", MonoidTests[FirstOption[Int]].monoid)
  checkAll("FirstOption[Int]", EqTests[FirstOption[Int]].eqv)
  checkAll("FirstOption[Int]", TraverseTests[FirstOption].traverse[Int, Int, Int, Int, Option, Option])

  test("combine"){
    1.some.asFirstOption    |+| 2.some.asFirstOption shouldEqual FirstOption(Some(1))
    none[Int].asFirstOption |+| 2.some.asFirstOption shouldEqual FirstOption(Some(2))
  }

  test("show") {
    FirstOption(Some("aString")).show shouldEqual "FirstOption(Some(aString))"
    FirstOption(Some(42)).show shouldEqual "FirstOption(Some(42))"
    FirstOption(Some(new ShowTestClass)).show shouldEqual s"FirstOption(Some(${ShowTestClass.show}))"
    FirstOption[Int](None).show shouldEqual "FirstOption(None)"
  }
}