Классы типов Scala и Haskell: универсальные экземпляры

Следующий класс и экземпляр типа Haskell:

class Able a where
  able :: a -> Int

instance Able Int where
  able x = x

обычно переводится на Scala так:

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

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

Теперь в Haskell я могу определить своего рода универсальный экземпляр и тем самым создать экземпляр для всех типов Maybe:

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

Это определяет экземпляр Able для Maybe Int, Maybe Bool и т. д. при условии, что существует экземпляр Able для Int, Bool и т. д.

Как бы это сделать на Scala?


person scravy    schedule 15.02.2016    source источник


Ответы (1)


Вы должны построить экземпляр из неявного параметра для экземпляра однорангового типа A. Например:

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)
person 0__    schedule 15.02.2016
comment
Гениально! Спасибо большое :) - person scravy; 16.02.2016