matryoshka
matryoshka copied to clipboard
Support for mutual recursion? + motivating example
Hi, I saw the talk from Greg Pfeil and found the park on mutual recursion really appealing.
I created a simple example of numeric and boolean operations that I would be happy to add to a documentation once I figure how to do traversals. It is a nice domain to document due to some obvious rewrites on boolean expressions.
I appreciate that we need a natural transformation to transform A
(is higher-kinded Functor a thing?). But not sure if there is further infrastructure around this.
sealed trait BoolAndCalcF[A[_],I]
// Using AtLeastTwoList as a more complex use case
case class And[A[_]](expressions: AtLeastTwoList[A[Boolean]]) extends BoolAndCalcF[A, Boolean]
case class Or[A[_]](expressions: AtLeastTwoList[A[Boolean]]) extends BoolAndCalcF[A, Boolean]
case class Not[A[_]](wrapped: A[Boolean]) extends BoolAndCalcF[A, Boolean]
case class BoolVal[A[_]](value: Boolean) extends BoolAndCalcF[A, Boolean]
// A bridge from calculation to booleans
case class Compare[A[_],I : Numeric, J: Numeric](left: A[I], op: CompOp, right: A[I]) extends BoolAndCalcF[A, Boolean]
case class Add[A[_], I : Numeric](left: A[I], right: A[I]) extends BoolAndCalcF[A, I]
//To show it would not compose with the rest due to Option
case class Divide[A[_], I : Numeric](left: A[I], right: A[I]) extends BoolAndCalcF[A, Option[I]]
case class Num[A[_], I : Numeric](value: I) extends BoolAndCalcF[A, I]
sealed trait CompOp
object CompOp {
case object GT extends CompOp
case object LT extends CompOp
case object EQ extends CompOp
case object NE extends CompOp
case object GE extends CompOp
case object LE extends CompOp
}
//import cats.data.OneAnd
//type AtLeastTwoList[A] = OneAnd[OneAnd[List,A],A]
case class AtLeastTwoList[A](head: A, second:A, tail: List[A]) {
def map[B](f: A => B) = AtLeastTwoList(f(head), f(second), tail.map(f))
def fold[B](h: A => B)(f: (B, A) => B): B = tail.foldLeft[B](f(h(head), second))(f)
}
Cool!
So, there’s a PR (#28) with a bunch of mutual-recursion stuff on it, including working examples. However, a regression in scalac means it doesn’t compile anymore. I have an in-progress PR against scalac, but haven’t had a chance to finish it up.
Hi Greg, thanks for the update, looks promising!