The Scala representation of ADT differs from Haskell in that its constructors have their own types. This is partly due to practical interoperability - using subtypes is natural on the JVM and has both advantages and disadvantages .
You encounter one of the drawbacks of having values statically typed as constructor types often complicates type inference and implicit resolution.
The types of instances of the class are statically permitted, and in your case, Show not contravariant, so the instance for Tree[T] not an instance for EmptyTree.type . The most idiomatic solution from Scalaz's point of view is to provide intelligent constructors that return the ADT type:
import scalaz.Show, scalaz.syntax.show._ sealed abstract class Tree[+T] object Tree { private[this] case object EmptyTree extends Tree[Nothing] private[this] case class Node[T](value: T) extends Tree[T] val emptyTree: Tree[Nothing] = EmptyTree def node[T](value: T): Tree[T] = Node(value) implicit def show[T]: Show[Tree[T]] = Show.showA[Tree[T]] }
Now you can write Tree.emptyTree.show .
Note that this problem also appears in even simpler contexts. For example, suppose we want to reset the list using Option as a battery:
scala> List(1, 2, 3).foldLeft(Some(0))((acc, i) => acc.map(_ + i)) <console>:11: error: type mismatch; found : Option[Int] required: Some[Int] List(1, 2, 3).foldLeft(Some(0))((acc, i) => acc.map(_ + i)) ^
Since the output type for Some(0) is Some[Int] and not Option[Int] , the type parameter that was specified for the foldLeft method is too restrictive for the map result.
It would be nice if the standard library provided Option.none and Option.some "constructors" for such cases, but this is not so, so you need to either put the type annotation on the first argument, or use something like Scalaz none and some :
scala> import scalaz._, Scalaz._ import scalaz._ import Scalaz._ scala> List(1, 2, 3).foldLeft(some(0))((acc, i) => acc.map(_ + i)) res0: Option[Int] = Some(6)
In your case, you apparently control the definition of ADT so that you can create smart constructors yourself.