Need help with implicit conversion and high order type

37 views
Skip to first unread message

Michael Bondar

unread,
May 25, 2016, 1:21:49 PM5/25/16
to scala-user
Hi. I've been struggling with this for a while and hope you guys can help me out.

I have a trait (or typeclass)

trait Presenter[A] {
 
def present(a: A): String
}

and few instances like

implicit val stringPresenter = new Presenter[String] {
 
def present(a: String): String = a
}

implicit val intPresenter = new Presenter[Int] {
 
def present(a: Int): String = a.toString
}

In addition I have a method which take care of conversion

case class Value(s: String)

implicit def present[A](v: A)(implicit presenter: Presenter[A]): Value =
 
Value(presenter.present(v))
}

All this implicits are used here

def format(v: Value*): String =
  v
.map(_.s).mkString("\n")

format
(1, "a", "c")

And everything works fine as long as I work with simple classes. However I need to support higher order types like this

format(1, "a", "c", Some(123))

And to be honest I have absolutely no clue how to do this. I wrote additional implicit which looks like that

implicit def optionPresenter[A](implicit presenter: Presenter[A]) = new Presenter[Option[A]] {
 
def present(a: Option[A]): String =
    a match
{
     
case Some(v) => presenter.present(v)
     
case None => "Nothing here"
   
}
}


But it doesn't work since there is no Presenter instance of presenter for Option[String], only method which should create it.

Do you guys have any idea how to make this work ?

Stephen Compall

unread,
Sep 10, 2016, 4:49:04 AM9/10/16
to Michael Bondar, scala-user
On 5/26/16 12:21 AM, Michael Bondar wrote:
And to be honest I have absolutely no clue how to do this. I wrote additional implicit which looks like that

implicit def optionPresenter[A](implicit presenter: Presenter[A]) = new Presenter[Option[A]] {
  def present(a: Option[A]): String =
    a match {
      case Some(v) => presenter.present(v)
      case None => "Nothing here"
    }
}


But it doesn't work since there is no Presenter instance of presenter for Option[String], only method which should create it.

There is such an instance, and you have correctly defined it, but that's not what's being looked for.  You can diagnose by trying to call your present method explicitly.

  Value.present(Some(123))  // will not work
  Value.present(Some(123): Option[Int])  // works

(The second line is a hint.)  Here's the error

....scala:41: could not find implicit value for parameter presenter: Presenter[Some[Int]]
  Value.present(Some(123))  // will not work
               ^
I hope you'll agree that optionPresenter does not return a value of type Presenter[Some[Int]]!


Do you guys have any idea how to make this work ?

You can

  1. Mark Presenter's type parameter contravariant (and make sure to never overlap Presenter's instances and never provide a "fallback" for Any or something, because it will always be chosen), or
  2. Make present more polymorphic.

Greetings,

Stephen.
Reply all
Reply to author
Forward
0 new messages