Scala Cats FreeMonad疑问:解释器为何需asInstanceOf[Id[A]]?
解决Cats Free Monad解释器中无需显式
asInstanceOf[A]的问题 我来帮你搞定这个问题——你遇到的强制转换确实是完全可以避免的,问题根源在于解释器的匹配分支里,返回值类型没有和你的代数类型定义被编译器正确对齐,而不是代数本身有问题。
问题出在哪?
你写的代数StartupActionA定义是没问题的,但在解释器的apply方法里,编译器没办法自动推断每个匹配分支对应的A类型,导致返回值和Id[A](也就是A本身)的类型不匹配,所以你不得不加asInstanceOf[A]来“骗”编译器。
举个例子:StartCluster是StartupActionA[Unit],对应的A是Unit,你写的println("...")本身返回的就是Unit,但编译器不知道当前匹配的fa是StartCluster时A就是Unit,所以它会认为返回值类型和Id[A]不兼容。
修正后的解释器写法
只需要给每个分支明确返回对应A类型的值,让编译器能正确推导类型即可:
object Interpreter extends (StartupActionA ~> Id) { override def apply[A](fa: StartupActionA[A]): Id[A] = fa match { case StartCluster => println("Starting up the Akka Cluster") () // 明确返回Unit,对应StartCluster的A=Unit case StartEventActorShard => system.actorOf(Props(new MyActor()), "MyActor") // 返回ActorRef,对应A=ActorRef case StartKafka(ref) => Some(ref) // 返回Option[ActorRef],对应A=Option[ActorRef] } }
额外说明
别忘了Id[A]其实就是Cats给A起的别名(type Id[A] = A),所以你的解释器本质上就是把StartupActionA[A]直接映射到A类型的值,只要每个分支返回的类型和对应case的StartupActionA的类型参数一致,编译器就能完美推导,完全不需要强制转换。
内容的提问来源于stack exchange,提问作者Rob O'Doherty
相关产品推荐
相关产品推荐

