2015-04-18 3 views
5

Mit unit = Try, Try ist keine Monade, weil die linke Einheit Gesetz scheitert.Ist es eine Monade versuchen, wenn Einheit = Erfolg?

Try(expr) flatMap f != f(expr) 

Aber was ist die Frage wird: Ist es Try eine Monade, wenn unit = Success?

In diesem Fall:

Success(expr) flatMap f == f(expr) 

So ist es eine Monade.

Ist mein Verständnis korrekt?

+3

verliert Dies ist in der Regel die Art und Weise Einheit für 'Try' geschrieben, und es kann argumentiert werden, th Es bricht immer noch das Kompositionsgesetz. Diese Diskussionen sind alle ziemlich hand-wellig und ich persönlich denke nicht, dass sie viel Wert haben. –

Antwort

2

Erhalten Sie eine Antwort von der Hilfe von Alexey im Coursera Forum:

Wenn unit = Success, für die linke Einheit Gesetz:

Success(throw new Exception) flatMap f == f(throw new Exception) // holds 
Success(s) flatMap (x => throw new Exception) == Failure(new Exception) // does not hold 

Es verliert tatsächlich wieder, außer natürlich, Sie neu definieren flatMap die Ausnahmen neu zu werfen, so dass die Hauptfunktionalität der Try

+0

Ich halte diesen Fall für völlig unbrauchbar. Man verwendet Try nicht, um Exceptions zu werfen. Es ist nur eine Schwäche der Scala, dass ein solcher Code geschrieben werden kann. Wenn Sie noch nicht überzeugt sind, dann setzen Sie diese Zeile in eine f. '' 'Thread.currentThread() getStackTrace.find (_.getMethodName.contains ("flatMap")) .foreach {_ => new Runtime werfen ("no Monade no cry")} '' 'und Sie können jede Monade tatsächlich ** töten ** in scala geschrieben. – jarek000000

3

Im Wesentlichen ja. Normalerweise werden Monaden in einer rein funktionalen Sprache definiert, in der Gleichheit == die üblichen Eigenschaften der Gleichheit hat, d. H. Wir können Gleiche für Gleichgestellte ersetzen. Wenn Sie innerhalb einer solchen Teilmenge von Scala sind, dann können Sie tatsächlich eine natürliche Definition eines parametrischen Typs geben, der möglicherweise außergewöhnliche Berechnungen darstellt. Hier ist ein Beispiel. Das Beispiel passiert tatsächlich mechanisch im Leon-Verifikationssystem für 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 
}