如何指定一个泛型函数,其工作方式就像存在 Int、Double 等超类型一样?

发布于 2024-12-09 17:18:47 字数 1096 浏览 0 评论 0原文

数字运算的存在(+-*、...)

def Arithmetic[T <: AnyVal](a: T, b: T) {
   val x = a + b
}

我需要定义一个类来保证基本 AnyVal 未定义 +。第二次尝试:

import Numeric.implicits._

def Arithmetic[T <% Numeric](a: T, b: T) {
   val x = a + b
}

到目前为止一切顺利,但现在我强制 T 为相同类型。因此,Arithmetic(double, int) 将失败。我真正的应用程序甚至更加人为:

class Arithmetic[T](A: Connector[T], B: Connector[U])(implicit n: Numeric[T]) {   
  val sum  = new Connector({ n.plus(A.value + B.value) })
}

class Constant[T](var x: T) {
  val value = new Connector({ x })
}

class Connector[T](f: => T) {
  def value: T = f
  override def toString = value.toString()
}

现在使用:

object Main extends App {
  val n1 = new Constant(1)

  // works
  val n5 = new Constant(5)
  val a = new Arithmetic( n1.value, n5.value )

  // doesn't work
  val n55 = new Constant(5.5)
  val b = new Arithmetic( n1.value, n55.value )
}

想法?建议?我只需要一些东西来保证我能够在课堂上进行基本的数学运算......

I need to define a class that guarantees the basic numeric operations will be present (+, -, *, ...)

def Arithmetic[T <: AnyVal](a: T, b: T) {
   val x = a + b
}

AnyVal does not define +. Second attempt:

import Numeric.implicits._

def Arithmetic[T <% Numeric](a: T, b: T) {
   val x = a + b
}

So far so good, but now I am forcing T to be of the same type. Hence Arithmetic(double, int) will fail. My real application is even a little more contrived:

class Arithmetic[T](A: Connector[T], B: Connector[U])(implicit n: Numeric[T]) {   
  val sum  = new Connector({ n.plus(A.value + B.value) })
}

class Constant[T](var x: T) {
  val value = new Connector({ x })
}

class Connector[T](f: => T) {
  def value: T = f
  override def toString = value.toString()
}

Now for the usage:

object Main extends App {
  val n1 = new Constant(1)

  // works
  val n5 = new Constant(5)
  val a = new Arithmetic( n1.value, n5.value )

  // doesn't work
  val n55 = new Constant(5.5)
  val b = new Arithmetic( n1.value, n55.value )
}

Thoughts? Suggestions? I just need something that guarantees I am able do basic math operations inside that class...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

五里雾 2024-12-16 17:18:47

认为你应该使用 上下文边界 在这里

def arithmetic[T: Numeric](a: T, b: T) = {
  import Numeric.Implicits._
  a + b
}

它可以工作,至少对于 <代码>scala 2.9.1

scala> arithmetic(1, 2.2)
res0: Double = 3.2

Think you should use context bounds here

def arithmetic[T: Numeric](a: T, b: T) = {
  import Numeric.Implicits._
  a + b
}

it works, at least for scala 2.9.1

scala> arithmetic(1, 2.2)
res0: Double = 3.2
沧桑㈠ 2024-12-16 17:18:47

这是一个想法:

class BiConverter[T, U, That](val toThat1: T => That, val toThat2: U => That)(implicit val num: Numeric[That])

trait LowPriorityBiConverterImplicits {
  implicit def subtype[A: Numeric, T <: A, U <: A]: BiConverter[T, U, A] = new BiConverter[T, U, A](identity, identity)
}

object BiConverter extends LowPriorityBiConverterImplicits {
  implicit def identityConverter[T: Numeric]: BiConverter[T, T, T] = new BiConverter[T, T, T](identity, identity)
  implicit def firstAsSecond[T, U](implicit conv: T => U, num: Numeric[U]): BiConverter[T, U, U] = new BiConverter[T, U, U](conv, identity)
  implicit def secondAsFirst[T, U](implicit conv: U => T, num: Numeric[T]): BiConverter[T, U, T] = new BiConverter[T, U, T](identity, conv)
}

class Arithmetic[T] private (A: Connector[T], B: Connector[T])(implicit n: Numeric[T]) {
  import Numeric.Implicits._
  val sum = new Connector(A.value + B.value)
}
object Arithmetic {
  def apply[T, U, That](A: Connector[T], B: Connector[U])(implicit conv: BiConverter[T, U, That], tIsThatEvidence: T =:= That = null, uIsThatEvidence: U =:= That = null): Arithmetic[That] = {
    val newA: Connector[That] =
      if (tIsThatEvidence != null) A.asInstanceOf[Connector[That]]
      else new Connector(conv.toThat1(A.value))
    val newB: Connector[That] =
      if (uIsThatEvidence != null) B.asInstanceOf[Connector[That]]
      else new Connector(conv.toThat2(B.value))
    new Arithmetic(newA, newB)(conv.num)
  }
}
class Constant[T](var x: T) {
  val value = new Connector(x)
}

class Connector[T](f: => T) {
  def value: T = f
  override def toString = value.toString()
}

用法:

val n1 = new Constant(1)

val n5 = new Constant(5)
val a = Arithmetic(n1.value, n5.value)
val sum1 = a.sum.value // Int
println(sum1)

val n55 = new Constant(5.5)
val b = Arithmetic(n1.value, n55.value)
val sum2 = b.sum.value // Double
println(sum2)

val nBig5 = new Constant(BigInt(5))
val c = Arithmetic(n1.value, nBig5.value)
val sum3 = c.sum.value // BigInt
println(sum3)

Here's an idea:

class BiConverter[T, U, That](val toThat1: T => That, val toThat2: U => That)(implicit val num: Numeric[That])

trait LowPriorityBiConverterImplicits {
  implicit def subtype[A: Numeric, T <: A, U <: A]: BiConverter[T, U, A] = new BiConverter[T, U, A](identity, identity)
}

object BiConverter extends LowPriorityBiConverterImplicits {
  implicit def identityConverter[T: Numeric]: BiConverter[T, T, T] = new BiConverter[T, T, T](identity, identity)
  implicit def firstAsSecond[T, U](implicit conv: T => U, num: Numeric[U]): BiConverter[T, U, U] = new BiConverter[T, U, U](conv, identity)
  implicit def secondAsFirst[T, U](implicit conv: U => T, num: Numeric[T]): BiConverter[T, U, T] = new BiConverter[T, U, T](identity, conv)
}

class Arithmetic[T] private (A: Connector[T], B: Connector[T])(implicit n: Numeric[T]) {
  import Numeric.Implicits._
  val sum = new Connector(A.value + B.value)
}
object Arithmetic {
  def apply[T, U, That](A: Connector[T], B: Connector[U])(implicit conv: BiConverter[T, U, That], tIsThatEvidence: T =:= That = null, uIsThatEvidence: U =:= That = null): Arithmetic[That] = {
    val newA: Connector[That] =
      if (tIsThatEvidence != null) A.asInstanceOf[Connector[That]]
      else new Connector(conv.toThat1(A.value))
    val newB: Connector[That] =
      if (uIsThatEvidence != null) B.asInstanceOf[Connector[That]]
      else new Connector(conv.toThat2(B.value))
    new Arithmetic(newA, newB)(conv.num)
  }
}
class Constant[T](var x: T) {
  val value = new Connector(x)
}

class Connector[T](f: => T) {
  def value: T = f
  override def toString = value.toString()
}

Usage:

val n1 = new Constant(1)

val n5 = new Constant(5)
val a = Arithmetic(n1.value, n5.value)
val sum1 = a.sum.value // Int
println(sum1)

val n55 = new Constant(5.5)
val b = Arithmetic(n1.value, n55.value)
val sum2 = b.sum.value // Double
println(sum2)

val nBig5 = new Constant(BigInt(5))
val c = Arithmetic(n1.value, nBig5.value)
val sum3 = c.sum.value // BigInt
println(sum3)
避讳 2024-12-16 17:18:47

这样的事情对你有用吗?

import Numeric.Implicits._

trait Add[A, B, Result] {
  def plus(a: A, b: B): Result
}

trait LowerPriorityAdd {
  implicit def addNumNum[M, N](implicit numM: Numeric[M], numN: Numeric[N]) = new Add[M, N, Double] {
    def plus(m: M, n: N) = m.toDouble + n.toDouble
  }
}

trait LowPriorityAdd {
  implicit def addYX[X, Y, Z](implicit addXY: Add[X, Y, Z]) = new Add[Y, X, Z] {
    def plus(y: Y, x: X) = addXY.plus(x, y)
  }
}

object Add extends LowPriorityAdd with LowerPriorityAdd {
  implicit object AddIntInt extends Add[Int, Int, Int] {
    def plus(i: Int, j: Int) = i + j
  }

  implicit object AddIntDouble extends Add[Int, Double, Double] {
    def plus(i: Int, d: Double) = i + d
  }
}

class Arithmetic[T, U, V](t: Connector[T], u: Connector[U])(implicit ev: Add[T, U, V]) {
  val sum: Connector[V] = new Connector(ev.plus(t.value, u.value))
}

class Constant[A](val x: A) {
  val value: Connector[A] = new Connector(x)
}

class Connector[A](f: => A) {
  def value: A = f
  override def toString = value.toString
}

def main(args: Array[String]): Unit = {
  val n1 = new Constant(1)

  // works
  val n5 = new Constant(5)
  val a = new Arithmetic( n1.value, n5.value )

  // works
  val n55 = new Constant(5.5)
  val b = new Arithmetic( n1.value, n55.value )

  // works
  val c = new Arithmetic(n55.value, n1.value)
}

Would something like this work for you?

import Numeric.Implicits._

trait Add[A, B, Result] {
  def plus(a: A, b: B): Result
}

trait LowerPriorityAdd {
  implicit def addNumNum[M, N](implicit numM: Numeric[M], numN: Numeric[N]) = new Add[M, N, Double] {
    def plus(m: M, n: N) = m.toDouble + n.toDouble
  }
}

trait LowPriorityAdd {
  implicit def addYX[X, Y, Z](implicit addXY: Add[X, Y, Z]) = new Add[Y, X, Z] {
    def plus(y: Y, x: X) = addXY.plus(x, y)
  }
}

object Add extends LowPriorityAdd with LowerPriorityAdd {
  implicit object AddIntInt extends Add[Int, Int, Int] {
    def plus(i: Int, j: Int) = i + j
  }

  implicit object AddIntDouble extends Add[Int, Double, Double] {
    def plus(i: Int, d: Double) = i + d
  }
}

class Arithmetic[T, U, V](t: Connector[T], u: Connector[U])(implicit ev: Add[T, U, V]) {
  val sum: Connector[V] = new Connector(ev.plus(t.value, u.value))
}

class Constant[A](val x: A) {
  val value: Connector[A] = new Connector(x)
}

class Connector[A](f: => A) {
  def value: A = f
  override def toString = value.toString
}

def main(args: Array[String]): Unit = {
  val n1 = new Constant(1)

  // works
  val n5 = new Constant(5)
  val a = new Arithmetic( n1.value, n5.value )

  // works
  val n55 = new Constant(5.5)
  val b = new Arithmetic( n1.value, n55.value )

  // works
  val c = new Arithmetic(n55.value, n1.value)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文