Scala多态回调类型不匹配

Scala多态回调类型不匹配,scala,types,callback,polymorphism,case-class,Scala,Types,Callback,Polymorphism,Case Class,很抱歉,我找不到更好的标题 我正在努力实现以下目标 abstract class Person case class User(uid: String, firstname: String, active: String) extends Person case class Admin(id: String, pseudo: String, securityClearance: String) extends Person def innerFunctionForUser(user: Us

很抱歉,我找不到更好的标题

我正在努力实现以下目标

abstract class Person 

case class User(uid: String, firstname: String, active: String) extends Person
case class Admin(id: String, pseudo: String, securityClearance: String) extends Person

def innerFunctionForUser(user: User): List[String] = {
  List() :+ user.uid :+ user.firstname :+ user.active
}

def innerFunctionForAdmin(admin: Admin): List[String] = {
  List() :+ admin.id :+ admin.psuedo :+ admin.securityClearance
}

def outerFunction(person: Person, innerFunction: (Person) => List[String]): List[String] = {
  innerFunction(person)
}
所以我可以这样使用它

val myUser = User("0c60c5b4-306d-4372-b60d-fd699c80e408", "joe", "false")
val myAdmin = Admin("178789", "jack", "high")

outerFunction(myUser, innerFunctionForUser)
outerFunction(myAdmin, innerFunctionForAdmin)
哪一个不进行类型检查

type mismatch;
 found   : User => List[String]
 required: Person => List[String]
我不能让innerFunction接受这样一个类型的人

def innerFunctionForUser(user: Person): List[String] = {
  List() :+ user.uid :+ user.firstname :+ user.active
}
def outerFunction(person: Person, innerFunction: (SomeCaseClass) => List[String]): List[String] = {
  innerFunction(person)
}
我在这里保持简单,但我需要具有不同类型参数和不同数量参数的case类。 所以我不能在抽象类Person中声明它们。 这会给

value uid is not a member of Person

value firstname is not a member of Person

value active is not a member of Playground.Person

如何使具有不同类型和数字参数的不同案例类计算为同一类型

和/或

如何使回调具有多态性,就像这样

def innerFunctionForUser(user: Person): List[String] = {
  List() :+ user.uid :+ user.firstname :+ user.active
}
def outerFunction(person: Person, innerFunction: (SomeCaseClass) => List[String]): List[String] = {
  innerFunction(person)
}
希望这足够清楚

感谢阅读,祝您阅读愉快。

User和Admin是Person的子类型,但User=>List[String]和Admin=>List[String]不是Person=>List[String]的子类型。User=>List[String]和Admin=>List[String]实际上是Person=>List[String]的超类型。函数类型A=>B与B有关,但与A相反

尝试使outerFunction

由于type class InnerFunction现在同样作用于不同的数据类型,因此它为案例类的所有字段生成值列表,您甚至可以派生它:

这将保证在编译时T的所有字段都是字符串。

User和Admin是Person的子类型,但是User=>List[String]和Admin=>List[String]不是Person=>List[String]的子类型。User=>List[String]和Admin=>List[String]实际上是Person=>List[String]的超类型。函数类型A=>B与B有关,但与A相反

尝试使outerFunction

由于type class InnerFunction现在同样作用于不同的数据类型,因此它为案例类的所有字段生成值列表,您甚至可以派生它:


这将保证在编译时T的所有字段都是字符串。

BTW,List:+user.uid:+user.firstname:+user.active不常见且不可读。您可以选择:Listuser.uid、user.firstname、user.active或user.uid::user.firstname::user.active::Nil我会选择前者。顺便说一句,您可能想看看。我知道发布的代码可能是对您的实际需求的一个粗略简化,但是如果您真正需要的只是一个case类参数列表[String],那么def innerFuncp:Product:List[String]=p.productIterator.map\u0.toString.toList将为您完成此操作。是的,这只是为了举例,但有点愚蠢,谢谢。顺便说一句,列表:+user.uid:+user.firstname:+user.active不常见且不可读。您可以选择:Listuser.uid、user.firstname、user.active或user.uid::user.firstname::user.active::Nil我会选择前者。顺便说一句,您可能想看看。我知道发布的代码可能是对您的实际需求的一个粗略简化,但是如果您真正需要的只是一个case类参数列表[String],那么def innerFuncp:Product:List[String]=p.productIterator.map\u0.toString.toList将为您执行此操作。是的,这只是为了示例,但有点愚蠢,谢谢。
trait InnerFunction[T] {
  def apply(t: T): List[String]
}

object InnerFunction {
  implicit def mkInnerFunction[T <: Product]: InnerFunction[T] =
    _.productIterator.map(_.asInstanceOf[String]).toList
}

def outerFunction[T](t: T)(implicit innerFunction: InnerFunction[T]): List[String] = 
  innerFunction(t)

      //or simply
// def outerFunction[T <: Product](t: T): List[String] =
//   t.productIterator.map(_.asInstanceOf[String]).toList
      //or
// def outerFunction(t: Product): List[String] =
//   t.productIterator.map(_.asInstanceOf[String]).toList

outerFunction(myUser) //List(0c60c5b4-306d-4372-b60d-fd699c80e408, joe, false)
outerFunction(myAdmin) //List(178789, jack, high)
import shapeless.ops.hlist.ToList
import shapeless.{Generic, HList}

trait InnerFunction[T] {
  def apply(t: T): List[String]
}

object InnerFunction {
  implicit def mkInnerFunction[T <: Product, L <: HList](implicit
    generic: Generic.Aux[T, L],
    toList: ToList[L, String]
  ): InnerFunction[T] = generic.to(_).toList
}

def outerFunction[T](t: T)(implicit innerFunction: InnerFunction[T]): List[String] = 
  innerFunction(t)

      //or simply
// def outerFunction[T, L <: HList](t: T)(implicit
//   generic: Generic.Aux[T, L],
//   toList: ToList[L, String]
// ): List[String] = generic.to(t).toList

outerFunction(myUser) //List(0c60c5b4-306d-4372-b60d-fd699c80e408, joe, false)
outerFunction(myAdmin) //List(178789, jack, high)