选项[io.databaker.env.EnvValue],但类型F在类型上是不变的 [英] Option[io.databaker.env.EnvValue], but type F is invariant in type

查看:47
本文介绍了选项[io.databaker.env.EnvValue],但类型F在类型上是不变的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码片段,但未编译:

I have the following code snippet, that does not get compiled:

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]

我做错了什么?

推荐答案

我已更改为覆盖 def get(v: env.EnvVariable): F[Option[env.EnvValue]] = F.pure(None) 并收到错误消息 not找到:值 F.我做错了什么?

I have changed to override def get(v: env.EnvVariable): F[Option[env.EnvValue]] = F.pure(None) and got the error message not found: value F. What am I doing wrong?

考虑在隐式F:Applicative[F]

def foo[F[_]](implicit F: Applicative[F]): F[Option[String]] = F.pure(None)
        |              |              |                        |
      type           value          type                 "type as value"

注意value参数F如何与type参数F<具有相同的名称/代码>.现在在值 F 上调用一个方法看起来就像我们在一个类型上调用一个方法

Note how the value parameter F has the same name as the type parameter F. Now calling a method on value F looks like as if we are calling a method on a type

F.pure(None)

在 Scala 中无法使用点语法调用类型上的方法,但从概念上讲,这就是我们正在做的 - 我们希望传达调用类型级别"的想法.功能.这个命名约定有效,因为值和类型存在于两个独立的宇宙中,因此我们可以重用同名无冲突.例如,考虑为什么以下是合法的

Invoking a method on a type using dot syntax is not possible in Scala, but conceptually that is what we are doing - we wish to convey the idea of invoking a "type-level" function. This naming convention works because values and types live in two separate universes so we can reuse the same name without clashes. For example, consider why the following is legal

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)

我们没有要使用的隐式值参数的名称,所以我们不能使用上面的约定技巧和调用

we do not have the name of implicit value parameter to work with, so we cannot use the above convention trick and call

F.pure(None)

同样,类型上的点符号严格来说是非法的,所以我们使用伴生对象和 main 方法技巧

because, again, dot notation on types is strictly speaking illegal, so instead we use the companion object with main method trick

Applicative[F].pure(None)

这是有效的,因为 Applicative 同伴有类似的东西

This works because Applicative companion has something like

Applicative {
  def apply[F[_]](implicit instance: Applicative[F]): Applicative[F] = instance
}

这么叫

Applicative.apply[F]

或更短

Applicative[F]

返回作用域中的隐式instance.在这一点上,我们确实有我们的可以使用,因此点符号变得合法

returns the implicit instance in scope. At this point we do have our value to work with and so dot notation becomes legal

Applicative[F].pure(None)
              |
    ok because invoked on a value

因此,您必须使用 Sync[F].pure(None) 而不是 F.pure(None) 进行调用,因为在您的特定情况下,您是使用上下文边界.

Therefore, you have to call with Sync[F].pure(None) instead of F.pure(None), because in your particular case, you are using context bounds.

这篇关于选项[io.databaker.env.EnvValue],但类型F在类型上是不变的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆