有几件事。一般来说你真的想避免
asInstanceOf
因为现在你可以
Expression2
对于任何类型,它都会在求值时崩溃,因为它实际上不是
Int
. 有几种方法可以缓解这种情况。您可以只修复
表达2
import scalaz._
import Scalaz._
trait Expression2[A] extends Product with Serializable
case class Lit[A](a: Int) extends Expression2[Int]
case class Add[A](a: Int, b: Int) extends Expression2[Int]
case class Mult[A](a: Int, b: Int) extends Expression2[Int]
type ExprAlg[A] = Free[Expression2, A]
def lit(a: Int): ExprAlg[Int] = Free.liftF(Lit(a))
def add(a: Int, b: Int): ExprAlg[Int] = Free.liftF(Add(a, b))
def mult(a: Int, b: Int): ExprAlg[Int] = Free.liftF(Mult(a, b))
val eval: Expression2 ~> Id = new (Expression2 ~> Id) {
override def apply[A](fa: Expression2[A]): Id[A] = eval(fa)
def eval[A](expression2: Expression2[A]): A = expression2 match {
case Lit(n) => n
case Add(a, b) => a+b
case Mult(a, b) => a*b
}
}
或者您可以将此功能与这样的操作关联起来。基本上,你可以把你的ADT中的案例
Add
例如:case类的参数类似于函数参数,您放入Extends中的类型是result类型。
import scalaz._
import Scalaz._
import spire.algebra._
import spire.implicits._
trait Expression2[A] extends Product with Serializable
case class Lit[A](a: A) extends Expression2[A]
case class Add[A](a: A, b: A)(implicit val ev:Semiring[A]) extends Expression2[A]
case class Mult[A](a: A, b: A)(implicit val ev:Semiring[A]) extends Expression2[A]
type ExprAlg[A] = Free[Expression2, A]
def lit[A](a: A): ExprAlg[A] = Free.liftF(Lit(a))
def add[A](a: A, b: A)(implicit ev:Semiring[A]): ExprAlg[A] = Free.liftF(Add(a, b))
def mult[A](a: A, b: A)(implicit ev:Semiring[A]): ExprAlg[A] = Free.liftF(Mult(a, b))
val eval: Expression2 ~> Id = new (Expression2 ~> Id) {
override def apply[A](fa: Expression2[A]): Id[A] = eval(fa)
def eval[A](expression2: Expression2[A]): Id[A] = expression2 match {
case Lit(n) => n
case x:Add[A] => x.ev.plus(x.a,x.b)
case x:Mult[A] => x.ev.times(x.a,x.b)
}
}
def program[A: Semiring](a:A,b:A) = for {
two <- lit(a)
four <- lit(b)
sum <- add(two, four)
} yield sum
println(program[Int](2,4).foldMap(eval) )
至于你的期权,我不太清楚你为什么要在这里解释为期权。如果你能做到
F ~> Id
对一些人来说
F
我是说,
F ~> Option
真的只是
Some
应用于第一次自然转化。