scalahaskelltypeclassimplicitscala-implicits

Scala vs Haskell typeclasses: "catchall" instances


The following Haskell type class and instance:

class Able a where
  able :: a -> Int

instance Able Int where
  able x = x

is commonly translated to Scala like so:

trait Able[A] {
  def able(a: A): Int
}

implicit object AbleInt extends Able[Int] {
  def able(a: Int) = a
}

In Haskell I can now define a sort of catch-all instance and thereby create an instance for all Maybe types:

instance Able a => Able (Maybe a) where
  able (Just a) = able a
  able Nothing  = 0

This defines an instance of Able for Maybe Int, Maybe Bool, etc. provided that there is an instance Able for Int, Bool, etc.

How would one do that in Scala?


Solution

  • You would construct the instance from an implicit parameter for the instance of the peer type A. For example:

    implicit def AbleOption[A](implicit peer: Able[A]) = new Able[Option[A]] {
      def able(a: Option[A]) = a match {
        case Some(x) => peer.able(x)
        case None    => 0
      }
    }
    
    assert(implicitly[Able[Option[Int]]].able(None)    == 0)
    assert(implicitly[Able[Option[Int]]].able(Some(3)) == 3)