1
votes

How would one encode the following constraint in Scala (pseudocode)?

def foo(x: T forSome { type T has a Numeric[T] instance in scope }) = {
  val n= implicitly[...] // obtain the Numeric instance for x
  n.negate(x) // and use it with x
}

In words: I need a type class instance for my input argument, but I don't care about the argument's type, I just need to obtain the instance and use it on my argument.

It doesn't have to be an existential type, but I need to avoid type parameters in the def's signature.

Edit: just to clarify, the standard approach in these cases, i.e.:

def foo[T: Numeric](x: T) = ...

doesn't work for me, as it requires the addition of a type parameter on the method.

Thanks.

2
Why can't you add type parameter?ghik
Because it would be a second type parameter in the method, which I don't want to expose to the user. And because it's second it cannot be inferred without inferring the first, but in my case the first cannot be inferred in principle. And because the whole thing is happening around macros, I cannot use something along the lines of: stackoverflow.com/a/10734268/1274237 as macros cannot be partially applied.ncreep
There is no second type parameter. That expands to def foo[T](x: T)(implicit num: Numeric[T]) = .... This is one type parameter, as far as I can count.0__
I meant to say, that in my actual use that would be a second parameter.ncreep

2 Answers

1
votes

I managed to make it work like this:

implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])

def foo(iwn: InstanceWithNumeric[_]) {
  def genFoo[T](iwn: InstanceWithNumeric[T]) {
    println(iwn.n.negate(iwn.inst))
  }
  genFoo(iwn)
}

And now:

scala> foo(1)
-1

scala> foo(1.2)
-1.2

Not the prettiest, but seems to work.

EDIT: You can avoid defining inner function like this:

implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T]) {
  def negate = n.negate(inst)
}

Also, if you want to make implicit conversion to InstanceWithNumeric globally visible, you can do something like this:

class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
object InstanceWithNumeric {
  implicit def apply[T: Numeric](inst: T) =
    new InstanceWithNumeric(inst)
}

If you want to understand how this works, read about so called implicit scope (this question seems to contain good explanation).

0
votes

Not quite sure what you are attempting, because it seems you need a type once you make the call to implicitly. Would the following work for you?

def foo(implicit x: Numeric[_]) {
   //code goes here.
}