在枚举上使用猫秀

Using Cats Show on enum

我需要为表达基本运算符的枚举实现 cat Show 实例。

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
    }

看完doc后,我尝试实现如下:

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

但是我在尝试执行 show 方法时遇到错误:

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]

是否有任何最佳实践方法来为枚举实施 cat Show?我的问题的根本原因是什么?任何建议或文档推荐将不胜感激。非常感谢

implicit val minusShow: Show[Expr.Minus] = Show.show(
    minus => show"${minus.left} - ${minus.right}"
  )

minus.left类型是Expr[Double],你应该先定义Show[Expr[Double]]这样它才能找到正确的隐式。

这是解决方案

implicit def exprShow[T]: Show[Expr[T]] = Show.show(
      num => Expr.eval(num).toString
    )