【问题标题】:Auto-Inferring a higher-kinded Aux Parameter from an Argument从参数自动推断更高种类的辅助参数
【发布时间】:2019-03-29 23:55:49
【问题描述】:

在之前的 SO 帖子中,我询问了如何创建使用具有更高种类类型的 Aux 模式(here,得到了很好的回复!)。现在根据回复,我试图进一步抽象一点,并从参数的类型中推断出实际的泛型参数。麻烦的是,似乎很难区分XX.type。这是我的代码:

// The are types that I want to convert to various things
sealed trait ConversionType
trait CaseA extends ConversionType
object CaseA extends CaseA // In this case, convert to an optional
trait CaseB extends ConversionType
object CaseB extends CaseB // In this case, convert to a future etc...

trait Converter[Prefix] {
  type Paramd[_]
  def create[N](n:N): Paramd[N]
}

// Create the mechanism to convert from the cases, only doing case A for now...
object Converter {
  type Aux[Prefix, Ret[_]] = Converter[Prefix] { type Paramd[N] = Ret[N] }

  // Shouldn't `Prefix` be automatically inferred?
  def apply[Prefix](prefix:Prefix)(implicit p:Converter[Prefix]): Aux[Prefix, p.Paramd] = p

  implicit def makeOptionParamd: Aux[CaseA, Option] =
    new Converter[CaseA] {
      type Paramd[N] = Option[N]
      override def create[N](n:N): Paramd[N] = Option[N](n)
    }
}

// This works
val v = Converter.apply[CaseA](CaseA).create("test")
// **** This breaks! Why? ****
val vv = Converter.apply(CaseA).create("test")

上面的虚线出现以下错误:

Error:(135, 29) could not find implicit value for parameter p: Test.this.Converter[Test.this.CaseA.type]
    val vv = Converter.apply(CaseA).create("test")

Error:(135, 29) not enough arguments for method apply: (implicit p: Test.this.Converter[SchemaMaker.this.CaseA.type])Test.this.Converter.Aux[SchemaMaker.this.CaseA.type,p.Paramd] in object Converter.
Unspecified value parameter p.
    val vv = Converter.apply(CaseA).create("test")

所以编译器没有连接对象CaseA和类型CaseA之间的点?有没有办法解决这个问题?

【问题讨论】:

    标签: scala generics typeclass type-level-computation


    【解决方案1】:

    你的对象CaseA在同一时间

    • CaseA.type 类型(因为它是单例对象)
    • 类型为CaseA(因为它扩展了CaseA

    当你调用时

    val vv = Converter.apply(CaseA).create("test")
    

    推断的类型PrefixCaseA.type(单例对象类型),并且找不到该类型的隐式。

    更明确:

    val works = Converter.apply(CaseA: CaseA).create("test")
    val fails = Converter.apply(CaseA: CaseA.type).create("test")
    

    强制您的代码编译的绝对最短的更改是在Prefix 前面添加一个- 以使Converter 逆变:

    trait Converter[-Prefix] {
      type Paramd[_]
      def create[N](n:N): Paramd[N]
    }
    

    但我不确定这是否是你想要的,因为我不知道你想用这些花哨的机器来达到什么目的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多