理解cats-effect中forceR方法定义:为何返回真实IO[B]类型?
关于Cats-Effect中IO.forceR方法的类型疑问
先看forceR的实现代码:
def forceR[B](that: IO[B]): IO[B] = // cast is needed here to trick the compiler into avoiding the IO[Any] asInstanceOf[IO[Unit]].handleError(_ => ()).productR(that)
关键操作拆解
- 第一步:通过
asInstanceOf[IO[Unit]]将当前IO实例强转为IO[Unit],这一步是为了绕过编译器的类型推导限制,避免出现IO[Any]的中间类型。 - 第二步:调用
handleError(_ => ()),根据handleError的类型签名def handleError[B >: A](f: Throwable => B): IO[B],这里的A是Unit(因为上一步转成了IO[Unit]),而f返回的是Unit类型的(),所以B的类型就是Unit,最终这一步返回的是IO[Unit]。 - 第三步:调用
productR(that),这个方法的语义是:先执行左边的IO(也就是前面的IO[Unit]),忽略它的执行结果,然后执行右边的that: IO[B],并返回它的结果。所以最终整个方法的返回类型自然就是IO[B],不管B是Int还是其他类型。
为什么能返回IO[Int]这类类型?
核心在于productR的类型特性:它接收右边的IO[B],并将整个表达式的类型统一为IO[B]。前面的handleError返回的IO[Unit]只是起到了“执行但忽略结果”的作用,最终的类型由传入的that决定。而开头的强转是为了让编译器在推导handleError的类型时,不会因为原IO的类型而推导出IO[Any],从而保证后续productR能正确保留B的类型。
内容的提问来源于stack exchange,提问作者Michaelzh
相关产品推荐
相关产品推荐

