简体   繁体   中英

Scala - construct method name from generic type?

I have the following method:

def toNumber[T <: AnyVal](value:String, default:T)(implicit n: Numeric[T]):T = {
    val str = value.trim
    var s = n.zero
    if (value.trim.isEmpty) {
      default
    } else {
      if (default.isInstanceOf[Long])
        s = n.plus(n.zero,str.toLong.asInstanceOf[T])
      else if (default.isInstanceOf[Int])
        s = n.plus(n.zero,str.toInt.asInstanceOf[T])
    }
    s
  }

Is it possible to streamline this somehow so it looks at the type of T (eg Int, Long, etc.) and uses it to call the right "to" method (eg toInt, toLong, etc.)?

As a bonus question, can I somehow limit T to just Int and Long rather than any subclass of AnyVal?

Thanks, John

If you want to limit T to specific numeric instances, it might be a good idea to provide your own typeclass (thus providing an answer to your initial question):

trait Natural[T] { def from(s : String) : T }
implicit object IntNatural = new Natural[Int] { 
  def from(s : String) = s.toInt 
}
implicit object LongNatural = new Natural[Long] { 
  def from(s : String) = s.toLong 
}

Then your method:

def toNumber[T : Natural](value : String, default : T) : T = 
  if (value.trim.isEmpty)
    default
  else 
    implicitly[Natural[T]].from(value.trim)


However, I would personally re-write this method signature as:

natural[Int]("42") getOrElse 23

And then users would use getOrElse default at the use-site. For example:

 natural[Int]("42") getOrElse 23 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM