2016-10-26 4 views
1

ReadYamlValueと呼ばれるPlay Json Reads[T]タイプとよく似たMonadのようなタイプを作成しました。cats + disciplineを使って関数のようなMonadをテストする方法

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

私は、このために猫Monadインスタンス作成:

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) 
} 

をそして私はMonadLawsとScalaCheckでそれをテストしたいです。

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クラスは、モナドでも、Functorでもないのですか?

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 
     } 
    } 
    } 
} 

しかし、それは平等の定義を少しsidesteppingされるように、これはと思われる:これを行うには

一つの方法は、任意のサンプルを生成し、結果の平等を比較することです。これを行うにはより正統的な方法がありますか?これは、任意のインスタンスを使用してのように見えます

答えて

1

はキルケはそれをしない方法です:

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

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

+0

これの唯一の欠点は、両方がうまく「読み取り」されるという単一の例を生成することは考えにくいようである。私はすべて16がエラーの結果となり、成功のケースがテストされないことを恐れる。これは 'MonadLaws'をテストする上で大変重要ですか? –

+0

デコード側では、circeは本当にいくつかの 'A'値を生成し、次にそれらをエンコードして、デコーダが同じことをするようにしてください。 –

関連する問題