fuzzycuffs
fuzzycuffs

Reputation: 139

Generics in Implicit Class

I have a have an implicit class like this

  private[this] implicit class OptionListUtil[A, B <: List[A]](option: Option[B]) {

      def defaultMap[C](f: A => C): Seq[C] = option.getOrElse(Seq.empty[A]).map(f)

But when I go ahead and call it on a Option[List[A]], I get the value defaultMap is not a member of Option[List[A]]

Intellij is not giving any hints so I'm pretty lost

Upvotes: 1

Views: 300

Answers (3)

Alexey Romanov
Alexey Romanov

Reputation: 170859

Generally, if a type parameter only appears once it's suspicious. In this case B is actually useless and you can simplify OptionListUtil to

private[this] implicit class OptionListUtil[A](option: Option[List[A]]) {
  def defaultMap[C](f: A => C): Seq[C] = option.getOrElse(Seq.empty[A]).map(f)
}

because Option is covariant. This is much simpler for type inference to handle.

Upvotes: 4

fuzzycuffs
fuzzycuffs

Reputation: 139

Looks like another way to address this is with higher kinded generics with the class signature like:

private[this] implicit class OptionListUtil[A, B[A] <: List[A]](option: Option[B[A]])

Upvotes: 0

shayan
shayan

Reputation: 1241

Go with this instead:

implicit class OptionListUtil[A,B](option: Option[B])(implicit ev: B <:< List[A]) {

  def defaultMap[C](f: A => C): Seq[C] = option.toSeq.flatMap(_.map(f))
}

The current scala compiler can't infer the type A in your B <: List[A] quite right yet. Asking for the implicit evidence of <:< in these cases helps the compiler with type inference.I read somewher that the new dotty compiler apparently doesn't have this issue.

Upvotes: 0

Related Questions