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