Reputation: 3575
Is it possible to have a type class that is applied to a sealed trait?
The following sealed Trait
sealed trait MyType
object Type1 extends MyType
object Type2 extends MyType
case class Type3(i:Int) extends MyType
And I want to enrich the trait with a 'show' function that can be represented using the following type class
trait Show[A] {
def show(a: A): String
}
And I would like to us it in a function that accepts a trait as an input
def show[A :< MyType](a: A)(implicit sh: Show[A]) = sh.show(a) // Will not compile
Usually I could do something like
implicit val type3CanShow: Show[Type3] =
new Show[Type3] {
def show(t: Type3): String = s"show ${t.i}"
}
To get this to work I have 2 problems: 1) How do I define the type class on a object instead of a class (i.e Type1 and Type 2) 2) How do I get it to accept work on a trait, and make sure that the type class is provided for 3 products of the sealed trait
To solve 2 I could do something like (doen't compile - assumes all 3 were case classes)
def show[A :< MyType](a: A)(implicit sh: Show[A]) =
a match {
case t: Type1 => sh.show(t)
case t: Type2 => sh.show(t)
case t: Type3 => sh.show(t)
}
UPDATE:
@thesamet solved 1. However, I would still like a better way to do 2.
Running code like this, without having to add the pattern matching from above
def doSomething(t: MyType) = {
show(t)
}
Upvotes: 0
Views: 461
Reputation: 6582
The code you pasted
def show[A :< MyType](a: A)(implicit sh: Show[A]) = sh.show(a) // Will not compile
does not compile since it should be <:
and not :<
to specify MyType
as the upperbound for A. The following does compile:
def show[A <: MyType](a: A)(implicit sh: Show[A]) = sh.show(a)
To define an implicit value for Type1
you have to specify the type of the singleton object:
implicit val ShowType1 = new Show[Type1.type] {
def show(a: Type1.type) = "Type1"
}
Similarly for Type2
:
implicit val ShowType2 = new Show[Type2.type] {
def show(a: Type2.type) = "Type2"
}
Try it!
println(show(Type1))
Upvotes: 1