I want to use type class to design convert interface and codes are as below:
case class Kilograms(value: Double)
case class Pounds(value: Double)
trait Convert[T, U] {
  def convert(input: T): U
}
object Convert {
  def apply[T:Convert, U:Convert] = implicitly[Convert[T,U]]
  def covert[T, U](input: T)(implicit c: Convert[T, U]): U = c.convert(input)
  implicit object kilogramsToPounds extends Convert[Kilograms, Pounds] {
      override def convert(input: Kilograms): Pounds = Pounds(input.value *   2.20462)
    }
  implicit object poundsToKilograms extends Convert[Pounds, Kilograms] {
      override def convert(input: Pounds): Kilograms = Kilograms(input.value / 2.20462)
    }
}
But compile error:
Error: wrong number of type arguments for A$A95.this.Convert, should be 2
 def apply[T:Convert, U:Convert] = implicitly[Convert[T,U]]
 Error: could not find implicit value for parameter e: A$A95.this.Convert[T,U]
  def apply[T:Convert, U:Convert] = implicitly[Convert[T,U]]
Error: not enough arguments for method implicitly: (implicit e:   A$A95.this.Convert[T,U])A$A95.this.Convert[T,U].
Unspecified value parameter e.
   def apply[T:Convert, U:Convert] = implicitly[Convert[T,U]]
If I change def apply[T:Convert, U:Convert] = implicitly[Convert[T,U]] into def apply[T, U](implicit c: Convert[T, U]): Convert[T, U] = c, no compile error!!!
I would like to know what's going on? Also, I look up some information, context bound is restricted with single type parameter(?) If I want to implement multiple type parameter type class, how should I do?
The context-bound syntax T : U only works for types U that have only one type parameter S (which conforms to T).
This is valid because you are manually declaring the implicit for Convert[T, U]:
def covert[T, U](input: T)(implicit c: Convert[T, U]): U = c.convert(input)
The following is not valid, because the compiler de-sugars the context bounds to Convert[T] and Convert[U] respectively, which doesn't make sense.
 def apply[T:Convert, U:Convert] = implicitly[Convert[T,U]]
(attempts to de-sugar to)
 def apply[T, U](implicit ev1: Convert[T], ev2: Convert[U]) = ...
See the SLS 7.4 - Context and View Bounds:
A type parameter
Aof a method or non-trait class may also have one or more context boundsA : T. In this case the type parameter may be instantiated to any typeSfor which evidence exists at the instantiation point thatSsatisfies the boundT. Such evidence consists of an implicit value with typeT[S].
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With