I need to implement the cats Show
instances for an enum which express the basic operators.
enum Expr[T]:
case Plus(left: Expr[Double], right: Expr[Double]) extends Expr[Double]
case Minus(left: Expr[Double], right: Expr[Double]) extends Expr[Double]
case Num(value: Double) extends Expr[Double]
object Expr {
def eval[T](expr: Expr[T]): T =
expr match {
case Plus(left, right) => eval(left) eval(right)
case Minus(left, right) => eval(left) - eval(right)
case Num(value) => value
}
After reading the doc, I tried to implement as following:
object ExprShow {
implicit val numShow: Show[Expr.Num] = Show.show(
num => num.value.toString
)
implicit val minusShow: Show[Expr.Minus] = Show.show(
minus => show"${minus.left} - ${minus.right}"
)
implicit val plusShow: Show[Expr.Plus] = Show.show(
plus => show"${plus.left} ${plus.right}"
)
}
But I got the errors when trying to execute the show method:
val test = Expr.Num(3.0)
test.show
[error] -- [E007] Type Mismatch Error:
[error] 69 | minus => show"${minus.left} - ${minus.right}"
[error] | ^^^^^^^^^^
[error] | Found: (minus.left : grox.Expr[Double])
[error] | Required: cats.Show.Shown
[error] Explanation
[error] ===========
[error]
[error] Tree: minus.left
[error]
[error] I tried to show that
[error] (minus.left : grox.Expr[Double])
[error] conforms to
[error] cats.Show.Shown
[error] but the comparison trace ended with `false`:
[error]
[error] ==> (minus.left : grox.Expr[Double]) <: cats.Show.Shown
[error] ==> (minus.left : grox.Expr[Double]) <: cats.Show.Shown (recurring)
[error] ==> grox.Expr[Double] <: cats.Show.Shown (left is approximated)
[error] ==> grox.Expr[Double] <: cats.Show.Shown (recurring)
[error] <== grox.Expr[Double] <: cats.Show.Shown (recurring) = false
[error] <== grox.Expr[Double] <: cats.Show.Shown (left is approximated) = false
[error] <== (minus.left : grox.Expr[Double]) <: cats.Show.Shown (recurring) = false
[error] <== (minus.left : grox.Expr[Double]) <: cats.Show.Shown = false
[error]
[error] The tests were made under a constraint with:
[error] uninstantiated variables: A
[error] constrained types: [A](f: A => String): cats.Show[A],
[error] [A](f: A => String): cats.Show[A]
...
----------
[error] -- [E008] Not Found Error:
[error] 15 | test.show
[error] | ^^^^^^^^^
[error] | value show is not a member of grox.Expr[Double]
Is there any best practice approach to implement cats Show
for enum? What's the root cause of my issue? Any suggestions or doc recommendation would be appreciated. Thanks a bunch
CodePudding user response:
implicit val minusShow: Show[Expr.Minus] = Show.show(
minus => show"${minus.left} - ${minus.right}"
)
minus.left
type is Expr[Double]
, you should define Show[Expr[Double]]
first so it could find the correct implicit.
Here is the solution
implicit def exprShow[T]: Show[Expr[T]] = Show.show(
num => Expr.eval(num).toString
)