I'm looking at the following code for handling errors in Scala:
package challenge1
import core._, Syntax._
sealed trait Error
case class Explosion(exception: Throwable) extends Error
case object NotFound extends Error
case object InvalidRequest extends Error
case object InvalidMethod extends Error
case object Unauthorized extends Error
object Error {
implicit def ErrorEqual =
Equal.derived[Error]
}
case class Fail[A](error: Error) extends Result[A]
case class Ok[A](value: A) extends Result[A]
sealed trait Result[A] {
def fold[X](
fail: Error => X,
ok: A => X
): X = this match {
case Fail(error) => fail(error)
case Ok(value) => ok(value)
}
def map[B](f: A => B): Result[B] =
flatMap(f andThen Result.ok)
def flatMap[B](f: A => Result[B]): Result[B] =
fold(Result.fail, f)
def getOrElse(otherwise: => A): A =
fold(_ => otherwise, identity)
def |||(alternative: => Result[A]): Result[A] =
fold(_ => alternative, _ => this)
}
...
Now I can see code here for handling exceptions using the Maybe Monad in Clojure:
(use '[clojure.contrib.monads :only [maybe-m]])
(defmacro maybe
([bindings return]
`(domonad maybe-m ~bindings ~return))
([bindings return else]
`(let [result# (maybe ~bindings ~return)]
(if (nil? result#)
~else
result#))))
Here Jim Duey explains exception handling in terms of continuations:
(defn mf-a [x]
(println "starting mf-a")
(fn [c]
(println "completing mf-a")
(c (inc x))))
(defn mf-b [x]
(println "starting mf-b")
(fn [c]
(println "completing mf-b")
(c (* 2 x))))
(defn mf-c [x]
(println "starting mf-c")
(fn [c]
(println "completing mf-c")
(c (dec x))))
(def fn8 (m-chain [mf-a mf-b mf-c]))
(Now I'm aware that all monads are continuations in a sense - I'm going to put that aside for now. If I have made a grave mistake - please help me out so I can correct the question).
I'm trying to wrap my head around this Scala code above. I'm trying to work out if it is based on Maybe or on Continuations.
My question is: Can we understanding the error monad in terms of the Maybe monad or the Continuation monad?
"In terms of" is a loose phrase. The Result
monad you've shown is more general than the Maybe
monad; indeed I'd say that Maybe
is a special case of Result
. And in turn continuation is more general still, and Result
can be seen as a special case of continuation - but that's the same as the sense in which all monads are continuations, so if that's not what you're asking about, I'm not sure what you could be asking. (I don't find the continuation perspective helpful for understanding because continuations are a very general construct, but maybe you do? But if so, it would have to be the sense in which all monads are continuations)
I would advise trying to understand Result
directly; it's pretty simple and the differences from the other two examples you give are important. That said, it might help think of it as "Maybe
, but with different possible values for None
(Fail(e)
for any e: Error
) rather than only one"; is that the "in terms of" you wanted?