Я пытаюсь понять свободные монады. Итак, с помощью руководств я написал игрушечный пример для игры, и теперь я не понимаю, почему он компилируется. Вот:
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)
}