Scala:Cats、OptionT[Future, T] 和 ApplicativeError
Scala: Cats, OptionT[Future, T] and ApplicativeError
前段时间我开始使用 Cats,发现 OptionT
在大多数情况下与 Future[Option[T]]
一起工作非常有用。但是我遇到了一个缺点,要使用 AplicativeError
我需要定义类型别名 type FutureOption[T] = OptionT[Future, X]
以匹配 AplicativeError
所需的 F[_]
并将表达式的类型明确指定为 FutureOption[T]
.
type FutureOption[T] = OptionT[Future, T] // definition to match F[_] kind
val x = OptionT.liftF(Future.failed(new Exception("error"))) : FutureOption[String] // need to specify type explicitly
x.recover {
case NonFatal(e) => "fixed"
}
如果我删除表达式的类型定义和显式类型说明,recover
将不可用,因为 OptionT[Future, T]
不匹配 F[_]
,因此无法转换隐含地 AplicativeErrorOps
.
不幸的是,下面的示例将无法运行,因为没有 recover
方法。
val x = OptionT.liftF(Future.failed(new Exception("error")))
x.recover {
case NonFatal(e) => "fixed"
}
有什么办法可以避免这种样板代码吗?至少我想避免将表达式类型明确指定为 FutureOption[T]
。
是的,至少有两种方法可以应对类型归属。
使用 lambda 类型(这可能很吓人):
val a: { type λ[A] = OptionT[Future, A] }#λ
使用像 kind-projector 这样的编译器插件,示例用法:
val a: Lambda[A => OptionT[Future, A]]
但是如果你想调用 Future
的 recover
,你总是可以这样做:
val x = OptionT.liftF(Future.failed(new Exception("error")))
x.value.recover ...
除了其他答案之外,我还建议您确保为您的构建启用 -Ypartial-unification
。
这是针对 partial unification of type constructors. You can find a more detailed explanation about the fix here 的修复。
启用部分统一后,您在问题中提供的代码可以正常编译。请注意,如果您使用的是 IDE(例如 Intellij),您可能会得到 "false negatives"(代码带有下划线表示不正确且代码完成不起作用),但 scalac/sbt/gradle 将编译就好了
前段时间我开始使用 Cats,发现 OptionT
在大多数情况下与 Future[Option[T]]
一起工作非常有用。但是我遇到了一个缺点,要使用 AplicativeError
我需要定义类型别名 type FutureOption[T] = OptionT[Future, X]
以匹配 AplicativeError
所需的 F[_]
并将表达式的类型明确指定为 FutureOption[T]
.
type FutureOption[T] = OptionT[Future, T] // definition to match F[_] kind
val x = OptionT.liftF(Future.failed(new Exception("error"))) : FutureOption[String] // need to specify type explicitly
x.recover {
case NonFatal(e) => "fixed"
}
如果我删除表达式的类型定义和显式类型说明,recover
将不可用,因为 OptionT[Future, T]
不匹配 F[_]
,因此无法转换隐含地 AplicativeErrorOps
.
不幸的是,下面的示例将无法运行,因为没有 recover
方法。
val x = OptionT.liftF(Future.failed(new Exception("error")))
x.recover {
case NonFatal(e) => "fixed"
}
有什么办法可以避免这种样板代码吗?至少我想避免将表达式类型明确指定为 FutureOption[T]
。
是的,至少有两种方法可以应对类型归属。
使用 lambda 类型(这可能很吓人):
val a: { type λ[A] = OptionT[Future, A] }#λ
使用像 kind-projector 这样的编译器插件,示例用法:
val a: Lambda[A => OptionT[Future, A]]
但是如果你想调用 Future
的 recover
,你总是可以这样做:
val x = OptionT.liftF(Future.failed(new Exception("error")))
x.value.recover ...
除了其他答案之外,我还建议您确保为您的构建启用 -Ypartial-unification
。
这是针对 partial unification of type constructors. You can find a more detailed explanation about the fix here 的修复。
启用部分统一后,您在问题中提供的代码可以正常编译。请注意,如果您使用的是 IDE(例如 Intellij),您可能会得到 "false negatives"(代码带有下划线表示不正确且代码完成不起作用),但 scalac/sbt/gradle 将编译就好了