Scala 如何在一个类中有一个协变参数以及一个函数来转换它?

Scala 如何在一个类中有一个协变参数以及一个函数来转换它?,scala,generics,covariance,contravariance,Scala,Generics,Covariance,Contravariance,我有一个非常简单的课程: case class Foo[+T](t: T) 现在我想添加一个参数来将T转换为Int。出于特定的原因,我不想使用类型类、隐式或任何基于继承的解决方案,因为这正是我建模的内容:一个包含一些数据的类和转换它的函数 所以我写 case class Foo[+T](t: T, f: T => Int) 或 当然,它不起作用,因为f在t上是逆变的。 有什么解决办法吗?你可以试试存在主义类型 case class Foo[+T](t: T, f: (_ <: T

我有一个非常简单的课程:

case class Foo[+T](t: T)
现在我想添加一个参数来将T转换为Int。出于特定的原因,我不想使用类型类、隐式或任何基于继承的解决方案,因为这正是我建模的内容:一个包含一些数据的类和转换它的函数

所以我写

case class Foo[+T](t: T, f: T => Int)

当然,它不起作用,因为f在t上是逆变的。
有什么解决办法吗?

你可以试试存在主义类型

case class Foo[+T](t: T, f: (_ <: T) => Int)
然后,当需要推断
U
时,可以使用“部分应用”模式

def mkFoo[T] = new PartiallyApplied[T]
class PartiallyApplied[T] {
  def apply[U <: T](t: T, f: U => Int) = Foo(t, f)
}

trait Parent
case class Child(i: Int) extends Parent

mkFoo[Parent](new Parent {}, (c: Child) => c.i)

也许你们班可以

case class Foo[+T](t: T) { 
  def f[U >: T](t1: U): Int = ??? 
}

否则它就是不变量
case类Foo[T](T:T,f:T=>Int)

你可以试试存在主义类型

case class Foo[+T](t: T, f: (_ <: T) => Int)
然后,当需要推断
U
时,可以使用“部分应用”模式

def mkFoo[T] = new PartiallyApplied[T]
class PartiallyApplied[T] {
  def apply[U <: T](t: T, f: U => Int) = Foo(t, f)
}

trait Parent
case class Child(i: Int) extends Parent

mkFoo[Parent](new Parent {}, (c: Child) => c.i)

也许你们班可以

case class Foo[+T](t: T) { 
  def f[U >: T](t1: U): Int = ??? 
}

否则它就是不变量
case类Foo[T](T:T,f:T=>Int)

您将如何调用Foo.f?在您的示例中,U:T是因为函数是逆变的。例如,如果T=Int,我希望能够通过(x:Int)=>x*2或(x:Any)=>42。还有一件事:我真的需要Foo成为一个case类,因为我依赖它来实现其他事情,比如自动持久性。@pm42如果
U>:T
,那么
Foo
对于
T
(如果没有
T
,你可以使
Foo
逆变
Foo[-T]
但是现在使用
t
f
它只是不变的)。你不能随意改变差异。如果
Foo[Int]
Foo[Any]
的话,你可以使
Foo
协变(
Foo[+T]
),但是你的
Foo[Int]
不是
Foo[Any]
,因为
(x:Int)=>x*2
不是一个函数
Any Int=/code>@pm42实际上这听起来有点像。在实际情况中,我不会将函数作为lambda传递,而是作为Function1 scala trait的实现传递。它将是一个case类,例如包含一个要解释的字符串。这个“函数”和其他任何函数一样,只是一个参数。您如何调用Foo.f?在您的示例中,是U:T,因为函数是逆变的。例如,如果T=Int,我希望能够通过(x:Int)=>x*2或(x:Any)=>42。还有一件事:我真的需要Foo成为一个case类,因为我依赖它来实现其他事情,比如自动持久性。@pm42如果
U>:T
,那么
Foo
对于
T
(如果没有
T
,你可以使
Foo
逆变
Foo[-T]
但是现在使用
t
f
它只是不变的)。你不能随意改变差异。如果
Foo[Int]
Foo[Any]
的话,你可以使
Foo
协变(
Foo[+T]
),但是你的
Foo[Int]
不是
Foo[Any]
,因为
(x:Int)=>x*2
不是一个函数
Any Int=/code>@pm42实际上这听起来有点像。在实际情况中,我不会将函数作为lambda传递,而是作为Function1 scala trait的实现传递。它将是一个case类,例如包含一个要解释的字符串。这个“函数”和其他任何函数一样只是一个参数。如果函数需要转换实际位于对象中的数据项,那么它不应该接受任何参数。否则,您的问题可以归结为“如何使函数参数协变?”您也可以问“如何使3为偶数?”如果函数需要转换实际位于对象中的数据项,则它不应接受任何参数。否则,您的问题可以归结为“如何使函数参数协变?”您也可以问“如何使3为偶数?”