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

问题描述 投票:0回答:1

我有一个非常简单的类。

case class Foo[+T](t: T)

现在我想添加一个参数来转换T到Int. 由于特殊的原因,我不想使用类型类、隐式或任何基于继承的解决方案,因为这才是我真正的建模:一个包含一些数据的类和转换数据的函数。

所以我写了

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

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

当然,这是行不通的,因为f在T上是反变的,有什么解决办法吗?

scala generics covariance contravariance
1个回答
2
投票

你可以尝试使用存在型

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

但实际上 (_ <: T) => Int 只是 Nothing => Int.

(在Dotty中,也可以拥有 case class Foo[+T](t: T, f: [U <: T] => U => Int).)

考虑再增加一个类型参数

case class Foo[+T, U <: T](t: T, f: U => 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)

还有一种选择是让 U 型人

trait Foo[+T] {
  type U <: T
  val t: T
  val f: U => Int
}

object Foo {
  def apply[T, _U <: T](_t: T, _f: _U => Int): Foo[T] { type U = _U } = new Foo[T] {
    override type U = _U
    override val t: T = _t
    override val f: U => Int = _f
  }

  def unapply[T](foo: Foo[T]): Option[(T, foo.U => Int)] = Some((foo.t, foo.f))
}

也许你的班级可以

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

否则就是不变的 case class Foo[T](t: T, f: T => Int).

© www.soinside.com 2019 - 2024. All rights reserved.