如何指定一个泛型函数,就好像存在超类型的Int,Double等一样? [英] How to specify a generic function that works as if there is a supertype of Int, Double, etc?

查看:129
本文介绍了如何指定一个泛型函数,就好像存在超类型的Int,Double等一样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要定义一个保证基本数值操作的类( + - ,<
$ b $ pre $ def算术[T * ,...)

](a:T,b:T){
val x = a + b
}

AnyVal 没有定义 + 。第二次尝试:

  import Numeric.implicits._ 

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

到目前为止这么好,但现在我强迫 T 为同一类型。因此算术(double,int)将失败。我真正的应用程序甚至更有人工作:

$ p $ class算术[T](A:连接器[T],B:连接器[U])(隐式n:数字[T]){
val sum =新连接器({n.plus(A.value + B.value)})
}

class常量[T](var x:T){
val值=新连接器({x})
}

类连接器[T](f:= > T){
def value:T = f
override def toString = value.toString()
}

现在用于:

 对象Main扩展应用程序{
val n1 = new常量(1)

//工程
val n5 =新常量(5)
val a = new算术(n1.value,n5.value)

//不起作用
val n55 =新常量(5.5)
val b = new算术(n1.value,n55.value)
}

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

解决方案

这是一个想法: p>

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

trait LowPriorityBiConverterImplicits {
隐式def子类型[A:数字,T <:A,U <:A]:BiConverter [T, U,A] = new BiConverter [T,U,A](identity,identity)
}

对象BiConverter扩展LowPriorityBiConverterImplicits {
隐式def identityConverter [T:Numeric]: BiConverter [T,T,T] = new BiConverter [T,T,T](identity,identity)
隐式def firstAsSecond [T,U](隐式conv:T => U,num: ]):BiConverter [T,U,U] = new BiConverter [T,U,U](conv,identity)
隐式def secondAsFirst [T,U](隐式conv:U => T,数字[T]):BiConverter [T,U,T] = new BiConverter [T,U,T](identity,conv)
}

类算术[T] private(A:Connector [T],B:Connector [T])(隐式n:数字[T]){
导入Numeric.Implicits._
val sum = new连接器(A.value + B.value)
}
对象算术{
def apply [T,U,That](A:Connector [T],B:Connector [U]) (隐式conv:BiConverter [T,U,That],tIsThatEvidence:T =:= That = null,uIsThatEvidence:U =:= That = null):Arithmetic [That] = {
val newA:Connector [ ] =
if(tIsThatEvidence!= null)A.asInstanceOf [Connector [That]]
else new Connector(conv.toThat1(A.value))
val newB:Connector [That]如果(uIsThatEvidence!= null)B.asInstanceOf [Connector [That]]
else new Connector(conv.toThat2(B.value))
new算术(newA,newB)( conv.num)
}
}
类常量[T](var x:T){
val值=新连接器(x)
}

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

用法:

  val n1 =新常数(1)

val n5 = new常量(5)
val a =算术(n1.value,n5.value)
val sum1 = a.sum.value // Int
println(sum1)

val n55 =新常量(5.5)
val b =算术(n1.value,n55.value)
val sum2 = b.sum.value // Double
println(sum2)

val nBig5 =新常量(BigInt(5))
val c =算术(n1.value,nBig5.value)
val sum3 = c .sum.value // BigInt
println(sum3)


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...

解决方案

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)

这篇关于如何指定一个泛型函数,就好像存在超类型的Int,Double等一样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆