辅助模式在嵌套的隐式中无法正常工作

huangapple go评论54阅读模式
英文:

Aux pattern not working for nested implicits

问题

以下是翻译好的代码部分:

sealed trait Types

object Types {
  case class A(value: Int) extends Types

  case class B(value: String, flag: Boolean) extends Types

  case class L(value: Types, n: Int) extends Types
}

trait Generate[In] {
  type Out

  def generate(in: In): Out
}

object Generate {

  type Aux[I, O] = Generate[I] {type Out = O}

  implicit object AGenerate extends Generate[Types.A] {
    override type Out = Int

    override def generate(a: Types.A): Out = a.value
  }

  implicit object BGenerate extends Generate[Types.B] {
    override type Out = String

    override def generate(b: Types.B): Out = if (b.flag) b.value else "nope"
  }

  implicit def lGenerate[T, O](implicit aux: Aux[T, O]): Generate[Types.L] = new Generate[Types.L] {
    override type Out = List[O]

    override def generate(in: Types.L): Out = List.fill(in.n)(aux.generate(in.value))
  }

  implicit class RichGenerator[I](in: I) {
    def generate[O](implicit aux: Aux[I, O]): O = aux.generate(in)
  }
}

object Test extends App {
  import Types._
  import Generate._

  val a = A(1)
  val b = B("yep", flag = true)

  println(a.generate) // 打印 1: Int
  println(b.generate) // 打印 "yep": String

  println(L(a, 3).generate) // 打印 List(1, 1, 1)
  println(L(b, 2).generate) // 打印 List("yep", "yep")
  println(L(L(a, 3), 2).generate) // 打印 List(List(1, 1, 1), List(1, 1, 1))
}

请注意,我已经将 " 替换为实际的引号字符。如果你有其他问题,请随时提出。

英文:

I have the following Types

sealed trait Types

object Types {
  case class A(value: Int) extends Types

  case class B(value: String, flag: Boolean) extends Types

  case class L(value: Types, n: Int) extends Types
}

I want to have a generate method that will generate an output based on the input type, and the output might have different types. I tried to use the Aux pattern and for type A and type B the values are generated.

trait Generate[In] {
  type Out

  def generate(in: In): Out
}

object Generate {

  type Aux[I, O] = Generate[I] {type Out = O}

  implicit object AGenerate extends Generate[Types.A] {
    override type Out = Int

    override def generate(a: Types.A): Out = a.value
  }

  implicit object BGenerate extends Generate[Types.B] {
    override type Out = String

    override def generate(b: Types.B): Out = if (b.flag) b.value else "nope"
  }

//  implicit def lGenerate[T, O](implicit aux: Aux[T, O]): Generate[Types.L] = new Generate[Types.L] {
//    override type Out = List[O]
//
//    override def generate(in: Types.L): Out = List.fill(in.n)(aux.generate(in.value))
//  }

  implicit class RichGenerator[I](in: I) {
    def generate[O](implicit aux: Aux[I, O]): O = aux.generate(in)
  }
}

object Test extends App {
  import Types._
  import Generate._

  val a = A(1)
  val b = B("yep", flag = true)

  println(a.generate) // prints 1: Int
  println(b.generate) // prints "yep": String
}

However, when I try to generate a value for type L, which depends on Types, then the implicit resolution fails.

My goal is to obtain the following outputs:

println(L(a, 3).generate) \\ prints List(1,1,1)
println(L(b, 2).generate) \\ prints List("yep", "yep")
println(L(L(a,3), 2).generate) \\ prints List(List(1,1,1), List(1,1,1)) 

答案1

得分: 2

你可能想要正确地将 Aux 类型链接在一起。

首先,让我们将 L 做成泛型:

final case class L[T <: Types](value: T, n: Int) extends Types

然后,让我们正确定义它的 Generator 实例:

implicit def lGenerate[T <: Types, O](implicit aux: Aux[T, O]): Aux[Types.L[T], List[O]] =
  new Generate[Types.L[T]] {
    override type Out = List[O]
  
    override def generate(in: Types.L[T]): Out =
      List.fill(in.n)(aux.generate(in.value))
  }

你可以在 这里 看到代码运行的效果。

英文:

You probably want to properly link the Aux types together.

First, let's make L generic:

final case class L[T &lt;: Types](value: T, n: Int) extends Types

Then, let's properly define its Generator instance:

implicit def lGenerate[T &lt;: Types, O](implicit aux: Aux[T, O]): Aux[Types.L[T], List[O]] =
  new Generate[Types.L[T]] {
    override type Out = List[O]
  
    override def generate(in: Types.L[T]): Out =
      List.fill(in.n)(aux.generate(in.value))
  }

You can see the code running here.

huangapple
  • 本文由 发表于 2023年7月18日 04:18:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707823.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定