1

Reads[T]と呼ばれるPlay Json 型によく似た Monad のような型を作成しましたReadYamlValue

trait ReadYamlValue[T] {
  def read(json: YamlValue): ReadResult[T]
  // ... methods include map, flatMap, etc
}

このための catMonadインスタンスを作成しました。

implicit val ReadYamlValueMonad: Monad[ReadYamlValue] = new Monad[ReadYamlValue] {
  override def flatMap[A, B](fa: ReadYamlValue[A])(f: A => ReadYamlValue[B]): ReadYamlValue[B] = {
    fa flatMap f
  }
  override def tailRecM[A, B](a: A)(f: A => ReadYamlValue[Either[A, B]]): ReadYamlValue[B] = {
    ReadYamlValue.read[B] { yaml =>
      @tailrec def readB(reader: ReadYamlValue[Either[A, B]]): ReadResult[B] = {
        reader.read(yaml) match {
          case Good(Left(nextA)) => readB(f(nextA))
          case Good(Right(b)) => Good(b)
          case Bad(error) => Bad(error)
        }
      }
      readB(f(a))
    }
  }
  override def pure[A](x: A): ReadYamlValue[A] = ReadYamlValue.success(x)
}

そして、MonadLawsScalaCheck でテストしたいと思いました。

class CatsTests extends FreeSpec with discipline.MonadTests[ReadYamlValue] {
  monad[Int, Int, Int].all.check()
}

しかし、私は得る:

could not find implicit value for parameter EqFA: cats.Eq[io.gloriousfuture.yaml.ReadYamlValue[Int]]

Eq実質的に関数を定義するにはどうすればよいですか? 関数の等価性を比較することは、私が望むものではないようです...私のReadYamlValueクラスはモナドでもファンクターでもありませんか?

これを行う 1 つの方法は、任意のサンプルを生成し、結果の等価性を比較することです。

implicit def eqReadYaml[T: Eq: FormatYamlValue: Arbitrary]: Eq[ReadYamlValue[T]] = {
  Eq.instance { (a, b) =>
    val badYaml = arbitrary[YamlValue].getOrThrow
    val goodValue = arbitrary[T].getOrThrow
    val goodYaml = Yaml.write(goodValue)
    Seq(badYaml, goodYaml).forall { yaml =>
      (a.read(yaml), b.read(yaml)) match {
        case (Good(av), Good(bv)) => Eq.eqv(av, bv)
        case (Bad(ae), Bad(be)) => Eq.eqv(ae, be)
        case _ => false
      }
    }
  }
}

しかし、これは平等の定義を少し回避しているようです。これを行うためのより良い、またはより標準的な方法はありますか?

4

1 に答える 1

1

Arbitrary インスタンスを使用することは、Circe が行う方法のようです。

https://github.com/travisbrown/circe/blob/master/modules/testing/shared/src/main/scala/io/circe/testing/EqInstances.scala

16 個のサンプルのストリームを取得し、結果を比較します。

于 2016-10-26T15:38:57.223 に答える