给定一个Fun
类型的单子
type FUN[A] = Map[String, String] => (List[String], A)
val funMonad: Monad[FUN] = new Monad[FUN] {
override def flatMap[A, B](fa: FUN[A])(f: (A) => FUN[B]): FUN[B] = m => {
val (list1, a1) = fa(m)
val (list2, a2) = f(a1)(m)
(list1 ++ list2, a2)
}
override def pure[A](x: A): FUN[A] = m => (Nil, x)
}
问题是:人类如何使用学科库来测试这个 Monad 实例是否遵守 Monad Laws?
以下是部分结果,由于编译器找不到隐式 for CartesianTests.Isomorphisms[FUN]
而失败。
import cats.Monad
import cats.kernel.Eq
import org.scalacheck.rng.Seed
import org.scalacheck.{Arbitrary, Gen}
class MyMonadSpec extends FunSuite with scalatest.Discipline {
...
implicit def funEq[T: Eq]: Eq[FUN[T]] = {
val sampleInput: Map[String, String] = {
def genMap: Gen[Map[String, String]] = for {
size <- Gen.size
keys <- Gen.containerOfN[List, String](size, Arbitrary.arbitrary[String])
values <- Gen.containerOfN[List, String](size, Arbitrary.arbitrary[String])
} yield keys.zip(values).toMap
genMap(Gen.Parameters.default.withSize(10), Seed.apply(123L)).get
}
Eq.instance[FUN[T]] ((f1, f2) => f1(sampleInput) == f2(sampleInput))
}
import cats.kernel.instances.int._
import cats.kernel.instances.tuple._
import cats.laws.discipline.MonadTests
checkAll("Int", MonadTests[FUN](funMonad).monad[Int, Int, Int])
//Error: could not find implicit value for parameter iso: cats.laws.discipline.CartesianTests.Isomorphisms[[A]scala.collection.immutable.Map[String,String] => (List[String], A)]