1

I am trying to create a type class with multiple type parameters. I am trying to invoke the method implicitly based on the types

I am showing a simple snippet of the code I have tried.

object operation {
// Define generic trait class
  trait Operator[T, U] {
    def addition[T, U](l: U, r: T)(implicit p: Parameters): U
  }


  object Operator {
// Define type class.
    implicit object IntOperator extends Operator[Int, Float] {
      def addition(l: Int, r: Float): Float = {
        r
      }
    }
  }
// Create mapping for implicit call.
  def addition[T, U](l: T, r: U)(implicit op: Operator[T, U]): U = op.addition(l, r,)
  }

import  operation._

def fn(a: UInt, b: Float)
addition(a,b)

If I use a single type parameter i.e., only [T,U] then this code compiles fine. However If I use two type parameters i.e., Operator[T,U] then the addition(a,b) complains No implicits found for parameter Operator[T,U]. Any help would be appreciated.

I hope the simplified code snippet elaborates on what I am trying to do.

2
  • 1
    Where is Parameters defined, why didn't you used it on your IntOperator, why are you re declaring T and U in addition on the trait?, was that a typo? Is the last addition call being done inside fn, if not from where did a and b came from? Commented May 29, 2019 at 0:07
  • 1
    Is UInt from the spire.math library? If so, the problem seems to be that implicit resolution for value classes doesn't use resolution for the underlying type. (I also had trouble getting your code to compile - you definitely need to remove the type parameters from def addition and correct the return type for IntOperator to even be recognised as a valid implementation.) Commented May 29, 2019 at 10:01

1 Answer 1

1

Just to let you know this compiles and works as expected.

object operation {
  trait Operator[T, U] {
    def addition(l: T, r: U): U
  }

  object Operator {
    implicit final val IntFloatOperator: Operator[Int, Float] =
      new Operator[Int, Float] {
        override def addition(l: Int, r: Float): Float = l + r
      }
  }

  def addition[T, U](l: T, r: U)(implicit op: Operator[T, U]): U = op.addition(l, r)
}

def fn(a: Int, b: Float): Float = operation.addition(a, b)
fn(1, 10.0f) // 11.0F

Edit

Addressing the comment you can either:

1) Provide the required implicit.

def fn[T1 <: Int, T2 <: Float](a: T1, b: T2)(implicit op: Operator[T1, U1]): U1 =
  op.addition(a, b)

(Note: The user of the method is in charge of having in scope an implicit of type Operator[T1, U1] for the types he/she is using.)

2) Explicitly summon the IntFloatOperator.

def fn[T1 <: Int, T2 <: Float](a: T1, b: T2): T2 = implicitly[Operator[Int, Float]].addition(a, b)

(Note: that it is common to provide a custom summoner, to reduce boilerplate.)

object Operator {
  // Summoner.
  def apply[T, U](implicit op: Operator[T, U]): Operator[T, U] = op

  ...
}

def fn[T1 <: Int, T2 <: Float](a: T1, b: T2): T2 =
  Operator[Int, Float].addition(a, b)
Sign up to request clarification or add additional context in comments.

7 Comments

I think I oversimplified the problem and introduced typos, while trying to ask the question. Let me try to rephrase. But thanks, for verifying the sample. I will try to fix my specific problem. --- Regards
Ok. I think I can replicate the error now. What happens if I make def fn[T<: Int, T2 <: Float](a : T, b: T2): Float = operation.addition(a, b). Now I get, could not find implicit value for parameter op: ammonite.$file.test.operation.Operator[T,T2]
@ArrvindhShriraman well, in that case the error is "pretty clear" it can not find the implicit, because fn does not provide it in any way. - I will asume in your real code you have something different that Int and Float (because it does not make sense to ask for subtypes of them). - So, to solve the problem there are two alternatives: 1) Your method ask for the implicit too, and in some way there should be an implicit instance available for the specific types being in use. 2) Since you asked why it did not found the IntOperator implicit, I guess you want to use that. I will edit.
Yes; that is correct. I have custom types and within fn I do not know the class of a and b, I only know their abstract i.e., fn itself is generic.
I tried your option 2 to summon the method using implicitly and it worked in the example you provided, but not in the case of my code. In my code, it now compains that T does not match the specific type. I think I have to repost my question and provide more details on my problem to make this work.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.