Scalacheckで、再帰的データ構造のArbitraryを作る場合にStackOverflowすることへの対策


具体的なエラーは以下のようなもの
https://travis-ci.org/xuwei-k/scalaz/builds/3721621/#L8699

Stacktraceをみれば明らかに再帰しているのはわかるのだけれど、おそらく単にStackOverflowしたあとに違うエラーもでて、最終的に

Could not create an instance of scalaz.xml.ContentTest
  caused by java.lang.Exception: Could not instantiate class scalaz.xml.ContentTest: null

となってしまっていたのが、わかりにくかったです。

で、冷静になって google:scalacheck arbitrary recursive でググったら一番上にScalacheckのMLでの議論がでてきました。


Arbitrary[Recursive] :scalacheck google group


もう2年以上まえですが、そのまま使えました。要約すると、


arbitrary[ List[...] ] とするとScalacheckはデフォルトでは0から100の長さのListを生成するので、

val b = choose(0,10) flatMap { n =>
  listOfN(n, arbitrary[Recursive]) map (BranchRecursive(_))
}

と、listOfN という関数を使って、小さいListを自作すればいいとのこと。



具体的には、Scalaz の xml のモジュールのテストを書いたときに遭遇したわけですが、以下のようにしたら正常に動きました

https://github.com/xuwei-k/scalaz/commit/60571b96e9a801fdb32f2f0e64843d2d636b7039