Summon Aux for higher-kinded type without reference to the original

旧城冷巷雨未停 提交于 2019-12-12 19:00:17

问题


I am trying to use the Aux pattern with a higher kinded type and not have to specify the parameter of the higher-kinded type until afterward. This is similar to the SO question described here but with one significant difference, I'm going the other way around, i.e. from an implicit def back to an aux.

// 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[_] = Ret[_] }

  // *** Error happens here! ***
  def apply[Prefix](implicit p:Converter[Prefix]): Aux[Prefix, p.Paramd] = p

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

// This seems to be fine...
val v = Converter.apply[CaseA].create("test")

I get the following compile error on the above noted line:

Error:(97, 78) type mismatch;
 found   : p.type (with underlying type Test.this.Converter[Prefix])
 required: Test.Converter.Aux[Prefix,p.Paramd]
    (which expands to)  Test.this.Converter[Prefix]{type Paramd[_] = p.Paramd[_]}
    def apply[Prefix](implicit p:Converter[Prefix]): Aux[Prefix, p.Paramd] = p

What am I doing wrong?


回答1:


What you probably want is

object Converter {
  type Aux[Prefix, Ret[_]] = Converter[Prefix] { type Paramd[A] = Ret[A] }

  // compiles
  def apply[Prefix](implicit p:Converter[Prefix]): Aux[Prefix, p.Paramd] = p

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

When you write

type Paramd[_] = Ret[_]

the _ in the left and the right parts are unrelated. It's the same as

type Paramd[A] = Ret[_]

type Paramd[A] = Ret[B] forSome { type B }

So Aux[Prefix, p.Paramd] with your definition is equivalent to Converter[Prefix] { type Paramd[A] = p.Paramd[_] }, and p doesn't have this type because p.Paramd[A] is not p.Paramd[_].



来源:https://stackoverflow.com/questions/55411471/summon-aux-for-higher-kinded-type-without-reference-to-the-original

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!