With unit = Try
, Try
is not a monad, because the left unit law fails.
Try(expr) flatMap f != f(expr)
But what is the question becomes: Is it Try
a monad, if unit = Success
?
In this case:
Success(expr) flatMap f == f(expr)
So it is a monad.
Is my understanding correct?
Got an answer from the Alexey's help in the coursera forum:
When unit = Success
, for the left unit law:
Success(throw new Exception) flatMap f == f(throw new Exception) // holds
Success(s) flatMap (x => throw new Exception) == Failure(new Exception) // does not hold
It actually loses again, unless of course you redefine flatMap to re-throw the exceptions, thus losing the main functionality of the Try
Essentially, yes. Usually monads are defined in a purely functional language, where equality == has the usual properties of equality, i.e. we can substitute equals for equals. If you are within such subset of Scala, then you can indeed give a natural definition of a parametric type that represents possibly exceptional computation. Here is an example. The example actually happens to mechanically verify in the Leon verification system for Scala (http://leon.epfl.ch).
import leon.lang._
object TryMonad {
// Exception monad similar to Option monad, with an error message id for None
sealed abstract class M[T] {
def bind[S](f: T => M[S]): M[S] = {
this match {
case Exc(str) => Exc[S](str)
case Success(t) => f(t)
}
}
}
case class Exc[T](err: BigInt) extends M[T]
case class Success[T](t: T) extends M[T]
// unit is success
def unit[T](t:T) = Success(t)
// all laws hold
def leftIdentity[T,S](t: T, f: T => M[S]): Boolean = {
unit(t).bind(f) == f(t)
}.holds
def rightIdentity[T](m: M[T]): Boolean = {
m.bind(unit(_)) == m
}.holds
def associativity[T,S,R](m: M[T], f: T => M[S], g: S => M[R]): Boolean = {
m.bind(f).bind(g) == m.bind((t:T) => f(t).bind(g))
}.holds
}
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