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

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

Aux pattern not working for nested implicits

问题

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

  1. sealed trait Types
  2. object Types {
  3. case class A(value: Int) extends Types
  4. case class B(value: String, flag: Boolean) extends Types
  5. case class L(value: Types, n: Int) extends Types
  6. }
  7. trait Generate[In] {
  8. type Out
  9. def generate(in: In): Out
  10. }
  11. object Generate {
  12. type Aux[I, O] = Generate[I] {type Out = O}
  13. implicit object AGenerate extends Generate[Types.A] {
  14. override type Out = Int
  15. override def generate(a: Types.A): Out = a.value
  16. }
  17. implicit object BGenerate extends Generate[Types.B] {
  18. override type Out = String
  19. override def generate(b: Types.B): Out = if (b.flag) b.value else "nope"
  20. }
  21. implicit def lGenerate[T, O](implicit aux: Aux[T, O]): Generate[Types.L] = new Generate[Types.L] {
  22. override type Out = List[O]
  23. override def generate(in: Types.L): Out = List.fill(in.n)(aux.generate(in.value))
  24. }
  25. implicit class RichGenerator[I](in: I) {
  26. def generate[O](implicit aux: Aux[I, O]): O = aux.generate(in)
  27. }
  28. }
  29. object Test extends App {
  30. import Types._
  31. import Generate._
  32. val a = A(1)
  33. val b = B("yep", flag = true)
  34. println(a.generate) // 打印 1: Int
  35. println(b.generate) // 打印 "yep": String
  36. println(L(a, 3).generate) // 打印 List(1, 1, 1)
  37. println(L(b, 2).generate) // 打印 List("yep", "yep")
  38. println(L(L(a, 3), 2).generate) // 打印 List(List(1, 1, 1), List(1, 1, 1))
  39. }

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

英文:

I have the following Types

  1. sealed trait Types
  2. object Types {
  3. case class A(value: Int) extends Types
  4. case class B(value: String, flag: Boolean) extends Types
  5. case class L(value: Types, n: Int) extends Types
  6. }

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.

  1. trait Generate[In] {
  2. type Out
  3. def generate(in: In): Out
  4. }
  5. object Generate {
  6. type Aux[I, O] = Generate[I] {type Out = O}
  7. implicit object AGenerate extends Generate[Types.A] {
  8. override type Out = Int
  9. override def generate(a: Types.A): Out = a.value
  10. }
  11. implicit object BGenerate extends Generate[Types.B] {
  12. override type Out = String
  13. override def generate(b: Types.B): Out = if (b.flag) b.value else "nope"
  14. }
  15. // implicit def lGenerate[T, O](implicit aux: Aux[T, O]): Generate[Types.L] = new Generate[Types.L] {
  16. // override type Out = List[O]
  17. //
  18. // override def generate(in: Types.L): Out = List.fill(in.n)(aux.generate(in.value))
  19. // }
  20. implicit class RichGenerator[I](in: I) {
  21. def generate[O](implicit aux: Aux[I, O]): O = aux.generate(in)
  22. }
  23. }
  24. object Test extends App {
  25. import Types._
  26. import Generate._
  27. val a = A(1)
  28. val b = B("yep", flag = true)
  29. println(a.generate) // prints 1: Int
  30. println(b.generate) // prints "yep": String
  31. }

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:

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

答案1

得分: 2

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

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

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

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

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

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

英文:

You probably want to properly link the Aux types together.

First, let's make L generic:

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

Then, let's properly define its Generator instance:

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

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:

确定