我是 cats-effect 的新手,我正在尝试使用 cats-effect 实现经典表达式评估。使用 eval 我想返回一个 IO[Double] 而不是 Double。我在下面有我的天真代码,但当然它没有类型检查。处理这个问题的正确方法是什么? (似乎通常使用模式匹配很难使用 IO)。
import cats.effect._
import cats.effect.unsafe.implicits.global
sealed trait Expression
case class Add(x: Expression, y: Expression) extends Expression
case class Mult(x: Expression, y: Expression) extends Expression
case class Exp(x: Expression) extends Expression
case class Const(x: Double) extends Expression
extension (exp: Expression)
def +(other: Expression) = Add(exp,other)
def *(other: Expression) = Mult(exp,other)
def eval(exp: Expression): IO[Double] = IO{
exp match
case Add(x, y) => eval(x) + eval(y) // This does not type check
case Mult(x, y) => eval(x) * eval(y)
case Exp(x) => scala.math.exp(eval(x))
case Const(x) => x
}
val expression1 = Exp((Const(1) + Const(2)) * Const(9))
@main def main =
println(eval(expression1).unsafeRunSync())
IO
是一个单子。尝试理解
def eval(exp: Expression): IO[Double] =
exp match
case Add(x, y) => for {
x1 <- eval(x)
y1 <- eval(y)
} yield x1 + y1
case Mult(x, y) => for {
x1 <- eval(x)
y1 <- eval(y)
} yield x1 * y1
case Exp(x) => for {
x1 <- eval(x)
} yield scala.math.exp(x1)
case Const(x) => IO(x)
或应用语法
import cats.syntax.apply.given
def eval(exp: Expression): IO[Double] =
exp match
case Add(x, y) => (eval(x), eval(y)).mapN(_ + _)
case Mult(x, y) => (eval(x), eval(y)).mapN(_ * _)
case Exp(x) => eval(x).map(scala.math.exp)
case Const(x) => IO(x)