我试图理解免费的单子。因此,在教程的帮助下,我编写了玩具示例来玩,现在我不明白为什么它会编译。这里是:
import cats.free.Free
import cats.instances.all._
import cats.~>
trait Operation[+A]
case class Print(s: String) extends Operation[Unit]
case class Read() extends Operation[String]
object Console {
def print(s: String): Free[Operation, Unit] = Free.liftF(Print(s))
def read: Free[Operation, String] = Free.liftF(Read())
}
object Interpreter extends (Operation ~> Option) {
// why does this compile?
override def apply[A](fa: Operation[A]): Option[A] = fa match {
case Print(s) => Some(println(s))
case Read() => Some(readLine())
}
}
object Main {
def main(args: Array[String]) {
val program = for {
_ <- Console.print("What is your name?")
name <- Console.read
_ <- Console.print(s"Nice to meet you $name")
} yield ()
program.foldMap(Interpreter)
}
}
我说的是解释器的应用方法。它应该返回 Option[A],但我可以在这里返回 Option[Unit] 和 Option[String],所以我认为它应该是编译错误。但事实并非如此。这段代码可以编译并且可以工作(尽管 Idea 告诉我这是一个错误)。这是为什么?
UPD:但是为什么不编译呢?
def test[A](o: Operation[A]): Option[A] = o match {
case Print(s) => Some(s)
case Read() => Some(Unit)
}