首页 > 解决方案 > Option[io.databaker.env.EnvValue],但类型 F 类型不变

问题描述

我有以下代码片段,它没有被编译:

trait Environment[F[_]] {
  def get(v: EnvVariable): F[Option[EnvValue]]
}

final class LiveBadEnvironment[F[_] : Sync] extends Environment[F] {
  override def get(v: env.EnvVariable): F[Option[env.EnvValue]] = None.pure[F]
}

编译器抱怨:

[error]  found   : F[None.type]
[error]  required: F[Option[io.databaker.env.EnvValue]]
[error]     (which expands to)  F[Option[io.databaker.env.EnvValue.Type]]
[error] Note: None.type <: Option[io.databaker.env.EnvValue], but type F is invariant in type _.
[error] You may wish to define _ as +_ instead. (SLS 4.5)
[error]   override def get(v: env.EnvVariable): F[Option[env.EnvValue]] = None.pure[F]

我究竟做错了什么?

标签: scalascala-cats

解决方案


这是一个最小化的问题示例,显示了引入pure扩展方法的导入:

scala> import cats.Applicative, cats.implicits._
import cats.Applicative
import cats.implicits._

scala> def foo[F[_]: Applicative]: F[Option[String]] = None.pure[F]
                                                            ^
   error: type mismatch;
    found   : F[None.type]
    required: F[Option[String]]
   Note: None.type <: Option[String], but type F is invariant in type _.
   You may wish to define _ as +_ instead. (SLS 4.5)

问题是 的类型None.pure[F]被推断为F[None.type],而预期的返回类型不会影响推断。如果您对上下文绑定和扩展方法脱糖,类型推断将按您的预期工作:

scala> def foo[F[_]](implicit F: Applicative[F]): F[Option[String]] = F.pure(None)
def foo[F[_]](implicit F: cats.Applicative[F]): F[Option[String]]

你也可以写出类似的东西Option.empty[String].pure[F]——有很多方法可以遇到这种问题(太精确的类型推断),还有很多方法可以解决它,你应该选择的主要是口味问题。


推荐阅读