Reputation: 92016
I need to define a type class Field
as follows:
trait Field[A] {
// Additive identity
def zero: A
// Multiplicative identity
def one: A
}
The Numeric
type class also provides the methods, zero
and one
.
I want that every class for which a Numeric
instance is available can be used wherever a class with Field
instance is required. For example, the following should work:
def func[F: Field](f: F) = println(f)
func(2)
Can you please suggest how to achieve this? I tried the following but it didn't work:
scala> implicit def numericToField[N](n: Numeric[N]) = new Field[N] {
| def zero = n.zero
| def one = n.one
| }
numericToField: [N](n: Numeric[N])java.lang.Object with Field[N]
scala> def func[F: Field](f: F) = println(f)
func: [F](f: F)(implicit evidence$1: Field[F])Unit
scala> func(2)
<console>:12: error: could not find implicit value for evidence parameter of type Field[Int]
func(2)
^
Upvotes: 4
Views: 294
Reputation: 386
You've almost got it. You just need to make this small change:
scala> implicit def numericToField[N](implicit n: Numeric[N]) = new Field[N] {
| def zero = n.zero
| def one = n.one
| }
Upvotes: 7
Reputation: 3584
Your solution is very nearly correct, but you should have defined func like so:
def func[F <% Field](f:F) = println(f)
As you defined it now, F must be a Field (or a subtype of Field), not just be convertible to one. The "F <% Field" notation means that all values that have an implicit conversion to Fields are also admissible. The second solution would also have worked if you had created an implicit Field[Int] instance somewhere in scope from the call to func(2).
Upvotes: 3