Scala 选项[io.databaker.env.EnvValue],但类型F在类型中是不变的
我有以下未编译的代码段:Scala 选项[io.databaker.env.EnvValue],但类型F在类型中是不变的,scala,scala-cats,Scala,Scala Cats,我有以下未编译的代码段: 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] } 编译器抱怨: [er
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]
[error]找到:F[None.type]
[错误]必需:F[选项[io.databaker.env.EnvValue]]
[错误](扩展为)F[选项[io.databaker.env.EnvValue.Type]]
[错误]注意:None.type这是一个最小化的问题示例,显示引入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)
您还可以编写类似于Option.empty[String].pure[F]
之类的内容。遇到这种问题有很多方法(太精确的类型推断),有很多方法可以解决这个问题,您应该选择哪种方法主要取决于您的品味
我已更改为覆盖def get(v:env.EnvVariable):F[Option[env.EnvValue]]=F.pure(None)
,并收到错误消息notfound:value F
。我做错了什么
考虑在隐式F:Applicative[F]
def foo[F[_]](implicit F: Applicative[F]): F[Option[String]] = F.pure(None)
| | | |
type value type "type as value"
注意值参数F
与类型参数F
具有相同的名称。现在对valueF
调用方法看起来就像是对类型调用方法一样
F.pure(None)
在Scala中,使用点语法调用类型上的方法是不可能的,但从概念上讲,这就是我们正在做的——我们希望传达调用“类型级别”函数的想法。这是因为值和类型存在于两个不同的世界中,因此我们可以重用相同的名称而不会发生冲突。例如,考虑为什么以下是合法的
scala> object f { def f[f](f: f): f = f }
| val Int: Int = 42
object f
val Int: Int = 42
现在,当使用上下文绑定的:
符号时
def foo[F[_]: Applicative]: F[Option[String]] = Applicative[F].pure(None)
我们没有使用隐式值参数的名称,因此不能使用上述约定的技巧和调用
F.pure(None)
因为,同样,类型上的点表示法严格来说是非法的,所以我们使用带有main方法技巧的伴随对象
Applicative[F].pure(None)
这是因为Applicative
companion有如下功能
Applicative {
def apply[F[_]](implicit instance: Applicative[F]): Applicative[F] = instance
}
这么叫
Applicative.apply[F]
或更短
Applicative[F]
返回范围中的隐式实例
。在这一点上,我们确实有我们的价值,所以点符号成为法律
Applicative[F].pure(None)
|
ok because invoked on a value
因此,您必须使用Sync[F].pure(None)
而不是F.pure(None)
调用,因为在您的特定情况下,您使用的是上下文边界。在我上面的示例中,我已更改为覆盖def get(v:env.EnvVariable):F[Option[env.EnvValue]=F.pure(None)
并收到错误消息未找到:值F
。我做错了什么?Scala中的x.type
是什么意思?@zero\u编码如果要显式引用F
,需要使用隐式参数列表(如上面的第二个示例所示),而不是上下文绑定(F[\uu]:Applicative
)x.type
是x
的单例类型,在None的情况下,type
是None
作为其唯一成员的类型。请您解释一下F
上下文中类型和值之间的差异。示例<代码> DEFO [F[[A] ](隐式F:应用[f]):F[Optr[Str] ] = F.Prime:(无)< />代码,为什么<代码> f < /代码>也是一个值?@ ZoooLoad考虑为什么下面是合法的:<代码> ValIt:int=42 。这里的Int
是用于值和类型的名称。因为Int
是值,同时也是类型@马里奥·加利克,你太棒了。
Applicative[F].pure(None)
|
ok because invoked on a value