(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?
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).
You may find the scalaz project interesting; it has lots of other (functional) stuff as well besides an implementation of monads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With