Ich werde meine Fragen mit Beispielen am unteren Rand wiederholen.Haskell Monad Flow Verständnis
Wenn ich m
oder k
sage, bezog ich mich auf die linken und rechten Werte im Funktionsaufruf, m >>= k
.
Es gibt diese Unschärfe im Verständnis von Monaden. Wenn m
eine Berechnung ist und k
ein Lambda-Ausdruck ist, bedeutet das, dass k
zwei Zwecken dient, wo es mit Bindungen im do-Block arbeiten kann und sie auch für andere Zwecke in der Monad-Instanzdefinition verwendet werden kann? Wenn ein Wert gebunden wird, bevor k
in seinem do-Block ausgewertet wird, werden Werte automatisch an ihn übergeben oder ist die Definition der Monad-Instanzmethoden, wo wir den einzigen Effekt der Propagierung auf k
definieren?
Ich bin vielleicht ein bisschen irreführend durch die Beispiele, die ich sehe, die immer das direkt vorhergehende gebundene Element an den Lambda-Ausdruck übergeben, wenn sie Monaden erklären. Selbst wenn die verwendete Notation pure-do-no-lambda ist, ist es immer das letzte gebundene Element, das unter der Haube an das versteckte Lambda übergeben wird. Ist es nun eine schlechte Übung, ein Lambda zu verwenden, das mehr als ein Argument benötigt, und es als k
in m >>= k
zu verwenden? Oder liege ich falsch, wenn wir annehmen, dass, wenn wir in einem do-Block arbeiten, nur ein Argument an den nächsten "versteckten" Lambda-Ausdruck übergeben wird und dass dieses eine Argument das unmittelbar vorher gebundene Element ist?
Ich werde nun meine Fragen mit Beispielen wiederholen.
do
a <- getLine
b <- getLine
putStrLn $ a ++ b
a
und b
sind in IO
Behälter auf Werte gebunden, die an der Ausführung getLine
zurückgeführt wird. Unter der Haube, welche der folgenden ist, wenn überhaupt, gleichwertig?
getLine >>= \a -> getLine >>= \b -> putStrLn (a ++ b)
OR
getLine >>= \a -> getLine >>= \(a, b) -> putStrLn (a ++ b)
Wir sehen, dass der Wert in dem IO
Behälter getLine
extrahiert und auf die Lambda-Ausdruck weitergegeben.
Wenn die erste korrekt ist, würde das nicht zu einem Fehler führen, da a
in der Monad-Definition nicht definiert wäre?
Ich zog die zweite aus der Luft. Ich habe keine Beweise gesehen, dass es das sein könnte, aber selbst wenn es nicht die richtige Antwort ist, können wir so etwas tun? Natürlich müssten wir alle Lambda-Ausdrücke, die mit >>=
verwendet werden, alle 2-Tupel in diesem Zusammenhang nehmen. Ist dieses Verhalten nicht allein durch unsere >>=
Definition bestimmt, zumindest wenn nur-Lambda-No-Do-Notation verwendet wird?
Können wir diesen Lambda-Ausdruck in der Monad-Definition verwenden und etwas übergeben, was dazu führt, dass der Bildschirm erneut gedruckt wird? Sollten wir?
Wenn wir wollten mit putStrLn
in der >>=
Definition arbeiten, würden wir einige beliebigen Wert k
aus, um passieren müssen, um die putStrLn
Funktion zu bekommen?
Vielen Dank. Frieden.
Beachten Sie, dass der Operator '>> =' tatsächlich assoziativ bleibt. Es ist nur so, dass die Lambda-Syntax '\ x -> ...' eine spezielle syntaktische Form ist, die "so viel wie möglich" verschlingt. –
@ K.A.Buhr Oh, du hast vollkommen recht. Bearbeitet. – Bergi