Frage

Ich lerne über Monaden und habe ein paar Fragen.

Dies ist, wo ich jetzt bin. Bitte korrigieren Sie mich, wenn ich falsch bin.

  • Das >>= Symbol ist ein Infixoperator. Infixoperatoren sind Funktionen, die zwei Argumente (linke Seite und rechte Seite) und einen Wert zurückgeben.

  • Das >>= Symbol wird der Operator bind und hat Unterschrift Monad m => m t -> (t -> m u) -> m u genannt. Allerdings scheinen die Arten nicht hier in einer Reihe aufstellen. Wir bekommen einen Wert vom Typ m t und das zweite Argument ist eine Funktion, die ein t nimmt. (Ich sehe nicht, wie die Punkte zu verbinden.)

  • Das muss bedeuten, dass die Bindefunktion irgendwie in der Lage ist, die m vom m t zu entfernen, um die t zu bekommen und an die Funktion übergeben.

Hier sind meine Fragen:

  • Ist die Fähigkeit, die m von m t etwas zu entfernen, die nur innerhalb eines solchen bind-Operator ist. Hat diese binden Betreiber einige besondere Privilegien oder etwas haben?

  • Was hat es mit Zustandsänderungen zu tun? Ich verstehe (ich glaube), dass das Ziel der Monaden ist zu Nebenwirkungen ‚wickeln‘, so dass sie vom Rest des Programms getrennt sind. Aber was ist die Rolle des Binde Operator in das?

War es hilfreich?

Lösung

  

Ist die Fähigkeit, die ‚M‘ von ‚M t‘ etwas zu entfernen, die nur innerhalb eines solchen bind-Operator ist. Hat diese binden Betreiber haben einige besondere Privilegien oder etwas?

Bind ist in keiner Weise ein Sonderfall, aber in der Regel wird es im selben Modul wie die Monaden Datentyp definiert werden. Daher könnte es wissen (und benutzt) Details, die nicht durch das Modul exportiert werden. Der üblicher Fall wäre, dass das Modul einen Datentyp exportiert, aber nicht, dass es Konstrukteuren oder andere Details über die Typen innere Struktur. Dann gilt für Code, der das Modul das Innenleben des Datentyps verwendet unsichtbar sind und dass der Code nicht direkt Werte dieses Typs ändern.

Im Gegensatz zu, die Funktionen innerhalb des Moduls definiert ist, wie zum Beispiel einig bindet Operator >>=, zugreifen kann, was sie aus dem Modul wie sie in definiert sind. So solche Funktionen könnten in der Lage sein, die Dinge zu tun, „externe“ Funktionen können nicht tun.

Ein Sonderfall ist die IO Monade, da sie nicht von einem Modul definiert ist, sondern in das Laufzeitsystem / Compiler gebaut. Hier ist der Compiler weiß um die inneren Details davon Implementierung ist und setzt Funktionen wie IO des >>=. Die Implementierungen dieser Funktionen sind in der Tat besonders privilegiert, da sie „außerhalb des Programms“ leben, aber dies ist ein Sonderfall, und diese Tatsache sollte aus Haskell nicht beobachtbar sein.

  

Was hat es mit Zustandsänderungen zu tun? Ich verstehe (ich glaube), dass das Ziel der Monaden ist zu Nebenwirkungen ‚wickeln‘, so dass sie vom Rest des Programms getrennt sind. Aber was ist die Rolle des Binde Operator in das?

Es ist nicht wirklich haben muß mit Zustandsänderungen zu tun, das ist nur ein Problem, das mit moands gehandhabt werden kann. Die IO Monade wird verwendet haben IO in einer bestimmten Reihenfolge ausgeführt werden, aber in der Regel Monaden sind nur Möglichkeiten von Funktionen zusammen kombiniert werden.

Im Allgemeinen wird eine Monade (genauer gesagt, es ist bind-Funktion) definiert eine Art und Weise, sollen bestimmte Funktionen zusammen, um größere Funktionen zusammengesetzt sein. Das Verfahren zum Kombinieren Funktion ist in den monadisch abstrahiert. Wie genau diese Kombination funktioniert oder warum wollen Sie Funktionen in einer solchen Art und Weise zu kombinieren, ist nicht wichtig, gibt eine Monade nur eine Möglichkeit, bestimmte Funktionen zu kombinieren in einer bestimmten Art und Weise. (Siehe auch diese „Monaden für C # Programmierer“ beantworten , wo ich wiederhole im Grunde, dass ein paar mal mit Beispielen.)

Andere Tipps

  

ist die Fähigkeit, die ‚M‘ von ‚M t‘ etwas zu entfernen, die nur innerhalb eines solchen bind-Operator ist.

Nun, es ist sicherlich möglich, innerhalb des Operators bind, als seine Art angibt:

(>>=) :: m a -> (a -> m b) -> m b

Die ‚run‘ Funktion für Ihre Monade kann dies in der Regel auch tun (einen reinen Wert von Ihrer Berechnung zurück).

  

das Ziel der Monaden ist zu ‚wickeln‘ Nebenwirkungen, so dass sie vom Rest des Programms getrennt werden

Hmm. Nein, Monaden lassen Sie uns Vorstellungen von Berechnung modellieren. Side-Bewirkung Berechnungen sind nur ein solcher Begriff, als Staat ist, Rückzieher, Fortsetzungen, Parallelität, Transaktionen, optional Ergebnisse, zufällige Ergebnisse, reversionsfähige Zustand, Nicht-Determinismus ... alle eine href <= "http: // Haskell .org / haskellwiki / Monad # Interesting_monads“rel = "noreferrer"> kann

Der IO Monade ist das, was Sie sich beziehen, nehme ich an. Es ist eine etwas seltsame Monade - es erzeugt Sequenzen von abstrakten Änderungen an den Staat der Welt, die dann von der Laufzeit ausgewertet werden. Bind nur läßt uns Sequenz Dinge in der richtigen Reihenfolge in dem IO-Monade -. Und der Compiler wird dann übersetzt all diese sequenziert Welt modifizierenden Aktionen in Imperativ Code, der diesen Zustand der Maschine ändert

Das ist sehr spezifisch für die IO Monade aber nicht Monaden im Allgemeinen.

Im Folgenden ist die Definition der Typklasse Monad.

class  Monad m  where

    (>>=)       :: forall a b. m a -> (a -> m b) -> m b
    (>>)        :: forall a b. m a -> m b -> m b
    return      :: a -> m a
    fail        :: String -> m a

    m >> k      = m >>= \_ -> k
    fail s      = error s

Jeder Typ-Instanz vom Typ-Klasse Monad definiert ihre eigene >>= Funktion. Hier ist ein Beispiel aus der Typ-Instanz Maybe:

instance  Monad Maybe  where

    (Just x) >>= k      = k x
    Nothing  >>= _      = Nothing

    (Just _) >>  k      = k
    Nothing  >>  _      = Nothing

    return              = Just
    fail _              = Nothing

Wie wir sehen können, weil die Maybe Version von >>= ist speziell definiert die Maybe Typ-Instanz zu verstehen, und weil sie definiert ist in einem Ort, die legalen Zugang zu der data Maybe a Daten Konstrukteurs Nothing und Just a hat, die Maybe Version >>= ist in der Lage, die a der in Maybe a auszupacken und geben sie durch.

durch ein Beispiel umgehen, könnten wir nehmen:

x :: Maybe Integer
x = do a <- Just 5
       b <- Just (a + 1)
       return b

De-gezuckert, die do-Notation wird:

x :: Maybe Integer
x = Just 5        >>= \a ->
    Just (a + 1)  >>= \b ->
    Just b

Welche auswertet wie:

  =                  (\a ->
    Just (a + 1)  >>= \b ->
    Just b) 5

  = Just (5 + 1)  >>= \b ->
    Just b

  =                  (\b ->
    Just b) (5 + 1)

  = Just (5 + 1)

  = Just 6

Die Typen tun in einer Reihe aufstellen, komischerweise. Hier ist, wie.

Beachten Sie, dass eine Monade ist auch ein Funktor. Die folgende Funktion wird für alle functors definiert:

fmap :: (Functor f) => (a -> b) -> f a -> f b

Nun ist die Frage: Sind diese Typen wirklich ausrichten? Nun ja. Bei einer Funktion von a b, dann, wenn wir eine Umgebung f haben, in dem a zur Verfügung steht, haben wir ein Umfeld, in der f b verfügbar ist.

In Analogie zu Syllogismus:

(Functor Socrates) => (Man -> Mortal) -> Socrates Man -> Socrates Mortal

Nun, wie Sie wissen, eine Monade ist ein Funktor mit binden und Rückkehr ausgestattet:

return :: (Monad m) => a -> m a
(=<<) :: (Monad m) => (a -> m b) -> m a -> m b

Sie können wissen, dass nicht dasselbe ist, es ist ein Funktor mit Rückkehr ausgestattet und kommen:

join :: (Monad m) => m (m a) -> m a

Sehen Sie, wie wir ein m Abschälen sind. Mit einer Monade m, kann man nicht immer von m a bekommen a, aber man kann immer von m (m a) zu m a erhalten.

Nun auf das erste Argument aussehen (=<<). Es ist eine Funktion vom Typ (a -> m b). Was passiert, wenn Sie diese Funktion übergeben fmap? Sie erhalten m a -> m (m b). Also, „Mapping“ über eine m a mit einer Funktion a -> m b gibt Ihnen m (m b). Beachten Sie, dass diese genau wie die Art des Arguments join. Das ist kein Zufall. Eine vernünftige Umsetzung von „bind“ sieht wie folgt aus:

(>>=) :: m a -> (a -> m b) -> m b
x >>= f = join (fmap f x)

In der Tat, binden und an ihnen teilnehmen hinsichtlich voneinander definiert werden:

join = (>>= id)

ich sehr empfehlen, dass Sie ( http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html ). Es gibt einen perfekten, gesunden Menschenverstand Grund, warum Monaden existieren.

  

Ich verstehe (ich glaube), dass das Ziel der Monaden ist zu ‚wickeln‘ Nebenwirkungen, so dass sie vom Rest des Programms getrennt sind.

Es ist eigentlich ein bisschen mehr subtiler. Monaden erlauben uns Sequenzierung in sehr allgemeiner Weise zu modellieren. Oft, wenn Sie zu einem Domainberater sprechen Sie sie wie zu sagen, etwas zu finden „zuerst versuchen wir X. Dann versuchen wir, Y, und wenn das nicht funktioniert, dann versuchen wir, Z“. Wenn Sie kommen, so etwas in einer herkömmlichen Sprache finden Sie zu implementieren, dass es nicht paßt, so haben Sie eine Menge zusätzlichen Code zu schreiben, was den Domain-Experten mit dem Wort gemeint zu decken „dann“.

In Haskell können Sie dies als eine Monade implementieren mit der „dann“ in den Operator bind übersetzt. So zum Beispiel habe ich einmal ein Programm, in dem ein Element aus Pools werden mußte zugewiesen nach bestimmten Regeln. Für den Fall 1 Sie es vom Pool X. nahm Wenn das leer war dann bewegt Sie Pool Y. auf für Fall 2 Sie hatte es gerade vom Pool Y. zu nehmen und so weiter für ein Dutzend oder so Fälle, darunter auch einige, wo Sie nahm die am wenigsten vor kurzem von dem Pool X oder Y verwendet ich eine benutzerdefinierte Monade für diesen Job speziell geschrieben, so dass ich schreiben konnte:

case c of
   1: do {try poolX; try poolY}
   2: try poolY
   3: try $ lru [poolX, poolY]

Es funktionierte sehr gut.

Natürlich beinhaltet dieses herkömmliche Modelle der Sequenzierung. Der IO-Monade ist das Modell, das alle anderen Programmiersprachen haben; es ist nur, dass in Haskell seines explizite Wahl eher als Teil der Umwelt. Die ST Monade gibt Ihnen die Speicher Mutation von IO, aber ohne den tatsächlichen Ein- und Ausgang. Auf der anderen Seite der Staat Monade können Sie Ihren Zustand auf einen einzigen Wert eines benannten Typs beschränken.

Für etwas wirklich Gehirn Biegen finden Sie unter dieser Blog-Eintrag über einen Rückwärtszustand Monade. Der Zustand breitet sich in die entgegengesetzte Richtung zu der „Ausführung“. Wenn Sie dies als wie ein Zustand Monade denken Ausführung einer Anweisung durch den nächsten folgte, dann ein „put“ wird der Zustandswert rückwärts in der Zeit zu einem der vorherigen „get“ senden. Was wirklich passiert, ist, dass eine für beide Seiten rekursive Funktion eingerichtet wird, dass nur dann, wenn es endet, keine Widersprüche sind. Ich bin mir nicht ganz sicher, wo eine solche Monade zu verwenden, aber es zeigt den Punkt über Monaden Berechnungsmodelle zu sein.

Wenn Sie noch nicht bereit sind, dann denken Sie nur an binden als überladbaren Semikolon. Das bekommt man einen ziemlich langen Weg.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top