Scala 如何从具有类型成员的trait转换为具有类型参数的case类

Scala 如何从具有类型成员的trait转换为具有类型参数的case类,scala,implicit-conversion,typeclass,Scala,Implicit Conversion,Typeclass,我不知道如何解决scala中的问题。也许有人能帮我 我有一个带有一些类型参数的case类操作,这个类可以由一个对参数类型一无所知的方法返回,例如一个来自string/json/xml的解析器 因此,我需要一种从ShadoweOperation到操作的转换方法,因为需要从一些数据中解析一个ShadoweOperation,并从中提取一个操作的类型化版本 我已经写了一个代码来表达这个问题,它被简化并尝试做一些不同的事情,但是如果这个问题可以解决,我也可以解决真正的需要 也许有一个解决方案,但我需要找

我不知道如何解决scala中的问题。也许有人能帮我

我有一个带有一些类型参数的case类操作,这个类可以由一个对参数类型一无所知的方法返回,例如一个来自string/json/xml的解析器

因此,我需要一种从ShadoweOperation到操作的转换方法,因为需要从一些数据中解析一个ShadoweOperation,并从中提取一个操作的类型化版本

我已经写了一个代码来表达这个问题,它被简化并尝试做一些不同的事情,但是如果这个问题可以解决,我也可以解决真正的需要

也许有一个解决方案,但我需要找到一个没有它的解决方案

object box {

  trait Transform[A, B] {
    def apply(in: A): B
  }
  object Transform {
    def instance[A, B](f: A => B): Transform[A, B] = new Transform[A, B] {
      override def apply(in: A): B = f(in)
    }
  }

  implicit class TransformOps[T](w: T) {
    def transform(implicit t: Transform[T, String]) = t(w)
  }

  trait ShadowedOperation {
    type I
    type O
    def param: String
    def otherParam: Int
    def in: I
    def out: O
  }

  object ShadowedOperation {
    // How can i do this in a generic, typed and wonderful way ???
    implicit def operationToString: Transform[ShadowedOperation, String] = ???
  }

  case class Operation[I0, O0](
    param: String,
    otherParam: Int,
    in: I0,
    out: O0
  ) extends ShadowedOperation {type I = I0; type O = O0}

  object Operation {
    implicit def operationToString[I, O](
      implicit
      iToString: Transform[I, String],
      oToString: Transform[O, String]
    ): Transform[Operation[I, O], String] =
      Transform.instance(in => s"${in.otherParam} - ${in.param} - ${iToString(in.in)} - ${oToString(in.out)}")
  }

  def fakeParseFromString(in: String): List[ShadowedOperation] = {
    // this simulate a parsing (or read from db) from string to extract the case class
    List(Operation("param", 0, "in!", "out!"), Operation("param", 0, "in!", 100))
  }

}


object Main extends App {

  import box._

  implicit val intToString: Transform[Int, String] = Transform.instance(_.toString)
  implicit val stringToString: Transform[String, String] = Transform.instance(_.toString)

  val op = Operation("param", 0, "in!", "out!")
  val shadowedOperationList = fakeParseFromString("imagine that this string contain a json")
  val opString = op.transform
  val shadowedOpString = shadowedOperationList.map(_.transform)
  println(opString)
  println(shadowedOpString)
}

提前感谢所有能够提供帮助的人

我做了一些改变:

将协方差/逆变换添加到变换[-A,+B]

引入类型ShadowedOperation.Aux[I0,O0]

修复了使用Aux类型返回fakeParseFromString的类型

从case类的同伴对象提升到trait的同伴对象的操作字符串,并进行相应的更改

导入的实例:import op_

整个代码:

  object box {

    trait Transform[-A, +B] {
      def apply(in: A): B
    }
    object Transform {
      def instance[A, B](f: A => B): Transform[A, B] = new Transform[A, B] {
        override def apply(in: A): B = f(in)
      }
    }

    implicit class TransformOps[T](w: T) {
      def transform(implicit t: Transform[T, String]) = t(w)
    }

    trait ShadowedOperation {
      type I
      type O
      def param: String
      def otherParam: Int
      def in: I
      def out: O

      implicit def operationToString(
                                      implicit
                                      iToString: Transform[I, String],
                                      oToString: Transform[O, String]
                                    ): Transform[ShadowedOperation.Aux[I, O], String] =
        Transform.instance(in => s"${in.otherParam} - ${in.param} - ${iToString(in.in)} - ${oToString(in.out)}")
    }

    object ShadowedOperation {
      type Aux[I0, O0] = ShadowedOperation { type I = I0; type O = O0 }
    }

    case class Operation[I0, O0](
                                  param: String,
                                  otherParam: Int,
                                  in: I0,
                                  out: O0
                                ) extends ShadowedOperation {type I = I0; type O = O0}


    def fakeParseFromString[I, O](in: Operation[I, O]): ShadowedOperation.Aux[I, O] = in

  }




  def main(args: Array[String]): Unit = {
    import box._

    implicit val intToString: Transform[Int, String] = Transform.instance(_.toString)
    implicit val stringToString: Transform[String, String] = Transform.instance(_.toString)

    val op = Operation("param", 0, "in!", "out!")
    val shadowedOperation = fakeParseFromString(op)
    import op._
    val opString = op.transform
    val shadowedOpString = shadowedOperation.transform
    println(opString)//0 - param - in! - out!
    println(shadowedOpString)//0 - param - in! - out!
  }
因此,在这里不需要不成形

当您只编写ShadowedOperation而不是ShadowedOperation.Aux[?,??]时,会丢失一些有关类型的信息。您必须找到一种方法来恢复有关I、O转换、显式指定类型、定义更多隐式等的信息。。否则它就不起作用了

例如,在更新的示例中,您可以编写

def fakeParseFromString(in: String): List[ShadowedOperation.Aux[String, Any]] = 
  List(Operation("param", 0, "in!","out!"), Operation("param", 0, "in!", 100))

implicit val anyToString: Transform[Any, String] = Transform.instance(_.toString)
val shadowedOpString = shadowedOperationList.map(_.transform)
println(shadowedOpString) 
// List(Operation(param,0,in!,out!), Operation(param,0,in!,100))

谢谢你的回复!问题是真正的fakeParseFromString不能从函数参数推断I和O类型。为了更好地解释这个问题,我已经改了题目