【问题标题】:Using implicit type evidence to satisfy type constraint使用隐式类型证据来满足类型约束
【发布时间】:2022-01-19 05:45:35
【问题描述】:

我正在尝试创建一个具有许多不受约束类型的构建器,该构建器可以构建具有约束类型的类。如何使用类型边界的隐式证据来满足类型约束?

比如说我想建一个类:

class NameClass[N <: String](name: N)

我使用的是这样的构建器:

class NameClassBuilder[N](n: N) {
  def name[NewN <: String](name: NewN) = new NameClassBuilder[NewN](name)

  def build(implicit ev: N <:< String) : NameClass[N] = new NameClass[N](n)
}

object NameClassBuilder {
  def builder : NameClassBuilder[Unit] = new NameClassBuilder[Unit]()
}

这个想法是您可以从一个虚拟类型/值开始,然后在添加字段时更新类型。通过使用类型正确的证据,您只能在类型有意义时构建它。

问题在于它无法编译,因为来自NameClassBuilder 的N 不满足NameClass 中的类型约束N &lt;: String,即使我已经提供了它的证据。

error: type arguments [N] do not conform to class NameClass's type parameter bounds [N <: String]
         def build(implicit ev: N <:< String) : NameClass[N] = new NameClass[N](n)

有没有什么办法可以利用证据来满足这个约束?

【问题讨论】:

    标签: scala implicit type-constraints


    【解决方案1】:

    您可以改为返回NameClass[N with String]。 N with String &lt;: String 代表任何 N,如果实际上是 N &lt;: String,则 N with String = N。 build 中的 N &lt;:&lt; String 需要将 n: N 转换为 N with String。

    def build(implicit ev: N <:< String): NameClass[N with String] = {
      type F[+X] = N with X
      new NameClass(ev.liftCo[F](n))
    }
    

    Complete example on Scastie

    【讨论】:

    • 不错!我发现我可以只使用.asInstanceOf[N with String],但这要好得多。
    【解决方案2】:

    您是在告诉编译器,当调用函数build 时,应该存在符合N &lt;:&lt; String 的隐含证据。但在NameClassBuilder范围内,N符合Any。

    你可以试试:

    class NameClassBuilder[N](n: N) {
      def name[NewN <: String](name: NewN) = new NameClassBuilder[NewN](name)
    
      def build[U <: String](implicit ev: N <:< String): NameClass[U] = new NameClass[U](n.asInstanceOf)
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-10
      • 2019-09-19
      • 2021-01-28
      • 1970-01-01
      • 2020-10-25
      • 2021-05-13
      • 2021-04-15
      • 1970-01-01
      • 2020-01-17
      相关资源
      最近更新 更多