Dies ist ein Follow-up zu meiner vorherigen Frage . Ich schrieb eine Monade (für eine Übung), die eigentlich eine Funktion ist, die Zufallswerte erzeugt. Es ist jedoch nicht als -Instanz der Typklasse scalaz.Monad
definiert.
Nun habe ich mir die Rng Bibliothek angesehen und festgestellt, dass sie Rng
als scalaz.Monad
definiert hat:
Ich frage mich also, wie genau die Nutzer davon profitieren. Wie können wir die Tatsache nutzen, dass Rng
eine Instanz der Typklasse scalaz.Monad
ist? Können Sie Beispiele nennen?
Einer der Vorteile ist, dass Sie viele nützliche Methoden in MonadOps
erhalten.
Zum Beispiel erzeugt Rng.double.iterateUntil(_ < 0.1)
nur die Werte, die kleiner als 0.1
sind (während die Werte größer als 0.1
übersprungen werden).
iterateUntil
kann für die Erzeugung von Verteilungsmustern mithilfe einer Zurückweisungsmethode verwendet werden.
Z.B. Dies ist der Code, der einen Beta-Verteilungs-Sample-Generator erzeugt:
Hier ist ein einfaches Beispiel. Angenommen, ich möchte eine zufällige Größe für einen Bereich auswählen und dann einen zufälligen Index innerhalb dieses Bereichs auswählen und dann sowohl den Bereich als auch den Index zurückgeben. Die zweite Berechnung eines Zufallswertes hängt eindeutig von der ersten ab - ich muss die Größe des Bereichs kennen, um einen Wert im Bereich auszuwählen.
Diese Art der Sache ist spezifisch, was monadische Bindung für ist - es erlaubt Ihnen, folgendes zu schreiben:
%Vor% Dies wäre nicht möglich, wenn wir keine Monad
-Instanz für Rng
hätten.
Wie jede Schnittstelle hat das Deklarieren einer Instanz von Monad[Rng]
zwei Dinge: Sie stellt eine Implementierung der Methoden Monad
unter Standardnamen bereit und drückt einen impliziten Vertrag aus, dass diese Methodenimplementierungen bestimmten Gesetzen entsprechen (in diesem Fall) , die Monadengesetze).
@Travis gab ein Beispiel für eine Sache, die mit diesen Schnittstellen implementiert wurde, die Scalaz-Implementierung von map
und flatMap
. Du hast recht, dass du diese direkt umsetzen kannst; Sie sind in Monad
"geerbt" (eigentlich ein bisschen komplexer als das).
Als Beispiel für eine Methode, für die Sie definitiv eine Scalaz-Schnittstelle implementieren müssen, wie wäre es mit sequence
? Dies ist eine Methode, die einen List
(oder allgemeiner ein Traversable
) von Kontexten in einen einzelnen Kontext für ein List
umwandelt, z. B.:
Aber das verwendet eigentlich nur Applicative[Rng]
(was eine Superklasse ist), nicht die volle Potenz von Monad
. Ich kann nicht wirklich an etwas denken, das Monad
direkt verwendet (es gibt ein paar Methoden auf MonadOps
, zB untilM
, aber ich habe noch nie einen von ihnen in Wut benutzt), aber vielleicht möchtest du ein Bind
für einen "Wrapper" -Fall, in dem Sie eine "innere" Monad
"innerhalb" Ihrer Rng
sachen haben, in diesem Fall ist MonadTrans
nützlich:
Um ganz ehrlich zu sein, ist Applicative
wahrscheinlich gut genug für die meisten Monad
Anwendungsfälle, zumindest die einfacheren.
Natürlich sind all diese Methoden Dinge, die Sie selbst implementieren können, aber wie jede Bibliothek ist der ganze Sinn von Scalaz, dass sie bereits implementiert sind und unter Standardnamen, was es für andere einfacher macht Leute, die Ihren Code verstehen.