Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monad trait in Scala

(How) is it possible to represent monads in Scala in a generic way (like the Monad typeclass in Haskell)? Is it somehow possible to define a trait Monad for this purpose?

like image 311
Dario Avatar asked Sep 07 '25 17:09

Dario


2 Answers

You could try something like this:

trait Monad[+M[_]] {
  def unit[A](a: A): M[A]
  def bind[A, B](m: M[A])(f: A => M[B]): M[B]
}

// probably only works in Scala 2.8
implicit def monadicSyntax[M[_], A](m: M[A])(implicit tc: Monad[M]) = new {
  private val bind = tc.bind(m) _

  def map[B](f: A => B) = bind(f compose tc.unit)

  def flatMap[B](f: A => M[B]) = bind(f)
}

implicit object MonadicOption extends Monad[Option] {
  def unit[A](a: A) = Some(a)

  def bind[A, B](opt: Option[A])(f: A => Option[B]) = opt flatMap f
}

You would of course define similar implicit objects for any other monad your heart desires. In Haskell terms, you can think of Monad like the typeclass and MonadicOption as a particular instance of that type class. The monadicSyntax implicit conversion simply demonstrates how this typeclass could be used to allow the use of Scala's for-comprehensions with anything which satisfies the Monad typeclass.

Generally speaking, most things in the Scala standard library which implement flatMap are monads. Scala doesn't define a generic Monad typeclass (though that would be very useful). Instead, it relies on a syntactic trick of the parser to allow the use of for-comprehensions with anything which implements the appropriate methods. Specifically, those methods are map, flatMap and filter (or foreach and filter for the imperative form).

like image 155
Daniel Spiewak Avatar answered Sep 10 '25 06:09

Daniel Spiewak


You may find the scalaz project interesting; it has lots of other (functional) stuff as well besides an implementation of monads.

like image 21
andri Avatar answered Sep 10 '25 05:09

andri