views:

955

answers:

3

(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?

+7  A: 

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

andri
+2  A: 

Scala achieves similar power to Haskell's type classes through use of implicit parameters, particularly view bounds and context bounds. You can see such things in use particularly on Scala 2.8, with traits like Ordering and Numeric.

That said, look at the Scalaz project. It has monads, functors, arrows... the whole shebang.

Daniel
+12  A: 

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).

Daniel Spiewak
Thank you, this was exactly what I was looking for. I just wanted to define generic monad functions and transformers in a general way ...
Dario
You're not actually going to use this for anything real, are you? :-) Seriously, I've been working with Scala for a while, and I've found that a lot of cases where Haskell would use the Monad typeclass just don't come up in Scala because of traits and subtyping. The typeclass given above, while cool, would certainly not be the idiomatic way to solve problems in Scala.
Daniel Spiewak
But they do come up. They come up all the time. A couple of times a day, I want `liftA2` or `sequenceA`. Granted, these only require Applicative rather than Monad, but still, if these don't come up in your programming then you must be writing something very simple.
Apocalisp
It's possible that I'm just not watching closely enough for the cases as they come up. Alternatively, I may be designing my code in such a way that other solutions work better. Scala allows for object-functional solutions to problems which require heavy functional magic in languages like Haskell or ML (e.g. using open-recursion rather than functor tricks).
Daniel Spiewak
@Daniel Spiewak: Of course it's real - Think of a monadic representation of an interpreter! It's awful without monadic abstraction!
Dario