简体   繁体   English

具有更高种类的Scalacheck问题:任意类型的隐式扩展的发散

[英]Scalacheck issue with higher kinds : diverging implicit expansion for type Arbitrary

I've defined a monad type class and I'm trying to verify its law with scalacheck. 我已经定义了一个monad类型的类,并且试图通过scalacheck验证其规律。

I have the following error : 我有以下错误:

diverging implicit expansion for type org.scalacheck.Arbitrary[(A, Box[B])]

My scalacheck code is the following : 我的scalacheck代码如下:

class OptionMonadSpec extends MonadSpec[String, String, String, Option](Monad.optionMonad)

abstract class MonadSpec[A, B, C, Box[_] : ClassTag](monad: Monad[Box])
(implicit boxArb: Arbitrary[Box[A]], aArb: Arbitrary[A], bArb: Arbitrary[B], cArb: Arbitrary[C])
  extends Properties(s"Monad for ${classTag[Box[_]]}") {
  property("left identity") = forAll { (f: (A => Box[B]), a: A) =>
    val boxA: Box[A] = monad.pure(a)
    monad.flatMap(boxA)(f) == f(a)
  }
  property("right identity") = forAll { box: Box[A] =>
    monad.flatMap(box)(monad.pure) == monad
  }
  property("associativity") = forAll { (f: (A => Box[B]), g: (B => Box[C]), box: Box[A]) =>
    val boxB: Box[B] = monad.flatMap(box)(f)
    monad.flatMap(boxB)(g) == monad.flatMap(box) { a =>
      val boxB: Box[B] = f(a)
      monad.flatMap(boxB)(g)
    }
  }
}

Did I miss soemthing in the implicit Arbitrary types ? 我是否想念隐式任意类型的东西?

Here is my monad : 这是我的单子:

trait Monad[Box[_]] extends Functor[Box] {

  def pure[A](a: A): Box[A]

  def flatMap[A, B](boxA: Box[A])(f: A => Box[B]): Box[B]

}

object Monad {

  implicit val optionMonad = new Monad[Option] {

    override def pure[A](x: A): Option[A] = Some(x)

    override def flatMap[A, B](boxA: Option[A])(f: A => Option[B]) = boxA.flatMap(f)

    override def map[A, B](boxA: Option[A])(f: A => B) = boxA.map(f)
  }
}

Thanks 谢谢

You have an implicit Arbitrary[Box[A]] in scope, but you don't have one for Arbitrary[Box[B]] (which Scalacheck needs to create one for A => Box[B] ) or for Arbitrary[Box[C]] (which it'll ask for afterwards). 您在范围内有一个隐式Arbitrary[Box[A]] ,但是没有一个用于Arbitrary[Box[B]] (Scalacheck需要为A => Box[B]创建一个)或为Arbitrary[Box[C]] (稍后会要求)。

A more principled approach would be to create something like 一种更原则的方法是创建类似

trait Arbitrary1[F[_]] {
  def liftArb[A](arb: Arbitrary[A]): Arbitrary[F[A]]
}

and provide Arbitrary1[Box] but it would require being more explicit when calling forAll . 并提供Arbitrary1[Box]但在调用forAll时需要更加明确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM