1

I'm experimenting with a method in Scala which is attempting to round numbers depending on how big they are, e.g. if the value is below 1 then it makes sense to round it by at least one decimal point; rather than remaining an integer. Here's what I'm trying:

  def roundSmart[A](num: A)(implicit numeric: Numeric[A]) = num match {
    case num if num < 1 => numeric.toDouble(num)
    case _ => numeric.toInt(num)
  }

Which throws this error:

value < is not a member of type parameter A

Of course the parameters need to accept a range of parameter types within the function signature as it may be taking integers or doubles so this has added a further complexity.

I've taken the conditional statement on the first case from this answer - Using comparison operators in Scala's pattern matching system and am eager to use a Functional Programming approach. Perhaps there is also some in-built scala function like Math.round() that could help to round the second condition rather than remove any decimals. Thanks!

Community
  • 1
  • 1

1 Answers1

1

TL;DR : every numeric methods you'll need are inside numeric

The error is self-explanatory: your type A (which is generic) does not have a < method.

However, what you have is a typeclass with all numeric methods in it, so you should probably import them:

import numeric._

This imports (among other things) implicit conversion to OrderingOps, which has the desired method. But this comparison cannot work, since 1 is not an A, it's an Int!

The solution is simply to use fromIntof numeric.

While we're at it, you will have unexpected results for input such as -234.2e123... You'd better do your test on the absolute value of your number (abs is also a method of numeric).

Also, if you want to do a simple test, there is no need to use pattern matching, a if else statement is enough

def roundSmart[A](num: A)(implicit numeric: Numeric[A]) = {
  import numeric._
  if (abs(num) < fromInt(1)) toDouble(num) else toInt(num)
}
Cyrille Corpet
  • 5,265
  • 1
  • 14
  • 31
  • Note that the return type will be `Double`, you might want to do something about this too. – Cyrille Corpet Apr 21 '17 at 13:09
  • Thanks for the response. So the error goes - great - however if it always returns a `Double` regardless of whether I wanted an `Integer` then it doesn't help to accomplish what I intend to do (please read the whole question to understand the purpose). So I must be using the wrong technique. Also the *pattern matching* is because I will have more than two conditions. – jesus g_force Harris Apr 26 '17 at 15:58
  • Since you have static typing, there must be a well defined return type. You should think about what you want it to be, depending on your use case. – Cyrille Corpet Apr 28 '17 at 12:39