valterriann
valterriann

Reputation: 1281

creating implicit type class instance in generic way for Seq collections

I'm trying to write a generic implicit instance for the following structure :

      object SmartHasher {
    
       trait GetSmartHash[T] {
          def calculateHash(value: T): Int
        }
    
        object syntax {
          implicit class GetHashOps[T: GetSmartHash](itemToBeHashed: T) {
            def hashItSmartway(implicit GetSmartHashInstance: GetSmartHash[T]): Int =
              GetSmartHashInstance.calculateHash(itemToBeHashed)
          }
    }

 object instances {
      import syntax._
     
     implicit def stringSmartHash: GetSmartHash[String] = (s: String) =>s.size % 10 // smart demo thing :D
     
}
 

Now I'm trying to define a generic implicit instance that works for any Vector, List, Or Array

where smarthash method for its elements are defined :

What type I shoud use instead of Seq , as Im trying with it and it doesnt work out ?

implicit def sequenceHash[T: GetSmartHash]: GetSmartHash[Seq[T]] =
        (sequence: Seq[T]) => sequence.map(element => element.hashItSmartway).product

If I define It for an exact collection like Vector :

 implicit def sequenceHash[T: GetSmartHash]: GetSmartHash[Vector[T]] =
            (sequence: Vector[T]) => sequence.map(element => element.hashItSmartway).product

then it works as I expected. Any suggestions to write this in generic way for theese 3 collections, to prevent for repeating simillar code 3 times? Regards.

Upvotes: 0

Views: 197

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51658

Try

object instances {
  import syntax._

  // stringSmartHash ...
   
  implicit def sequenceHash[Col[X] <: Iterable[X], T: GetSmartHash]: GetSmartHash[Col[T]] =
    (sequence: Col[T]) => sequence.map(element => element.hashItSmartway).product
}

Testing:

import instances._, syntax._
List("aa", "bbb").hashItSmartway //6
Seq("aa", "bbb").hashItSmartway //6
Vector("aa", "bbb").hashItSmartway //6

If you want sequenceHash to work also for Array replace upper bound with view bound

implicit def sequenceHash[Col[_], T: GetSmartHash](implicit ev: Col[T] => Iterable[T]): GetSmartHash[Col[T]] =
  (sequence: Col[T]) => sequence.map(element => element.hashItSmartway).product

Upvotes: 2

Related Questions