idiomatic way to solve chicken-egg in scala -
how nicely initialize structures that:
case class a(name: string, b: b) case class b(name: string, a: a)
looking solution without lazy vals (performance overhead) , without adding new members existing case class (it looks ugly), special wrappers , changes of original type-signature maybe fine (at least it's best i've got now). tostring-problem negligible can override in trait.
for now, came this:
case class chicken[t](h: holder[t, _]) { def = h.chicken override def tostring = get.tostring } case class egg[u](h: holder[_, u]) { def = h.egg override def tostring = get.tostring } implicit def egg[t] = (_: egg[t]).get implicit def chicken[t] = (_: chicken[t]).get case class holder[u, t] (chickenf: (egg[t], chicken[u]) => (u, t)) { val (chicken, egg) = chickenf( egg(this), chicken(this)) } def mutual[u, t](chickenf: (egg[t], chicken[u]) => (u, t)) = { val h = new holder(chickenf) h.chicken -> h.egg } trait named { //to avoid unfinite tostring def name: string override def tostring = name }
usage:
case class a(name: string, b: egg[b]) case class b(name: string, a: chicken[a]) extends named val (a, b) = mutual[a, b](a("a", _) -> b("b", _)) val (a2, b2) = mutual[a, b]{ (b2, a2) => //alternative complex cases a("a", b2) -> b("b", a2) } println(a) println(b) println(a.b) println(b.a)
results:
a(a,b) b b a(a,b)
still hope there library that, scalaz or some-macro based solution.
Comments
Post a Comment