Monoiden
Sie werden feststellen, dass das Leben viel einfacher wird, wenn Sie erkennen, dass Sie auf den Schultern von Riesen stehen und von gemeinsamen Abstraktionen und den Bibliotheken profitieren können, die für ihre Verwendung erstellt wurden. Zu diesem Zweck geht es bei dieser Frage im Grunde darum, mit Monoiden umzugehen (siehe unten stehende verwandte Fragen für weitere Informationen dazu) und die genannte Bibliothek heißt scalaz.
Mit scalaz FP ist dies einfach:
def add(a: Option[Int], b: Option[Int]) = ~(a |+| b)
Darüber hinaus funktioniert dies für jeden Monoid M:
def add[M: Monoid](a: Option[M], b: Option[M]) = ~(a |+| b)
Noch nützlicher ist, dass es für beliebig viele von ihnen innerhalb eines Foldable
-Containers funktioniert:
def add[M: Monoid, F: Foldable](as: F[Option[M]]) = ~as.asMA.sum
Beachten Sie, dass einige recht nützliche Monoiden, abgesehen von den offensichtlichen Int
, String
, Boolean
Map[A, B: Monoid]
A => (B: Monoid)
Option[A: Monoid]
In der Tat lohnt es sich kaum, Ihre eigene Methode zu extrahieren:
scala> some(some(some(1))) #:: some(some(some(2))) #:: Stream.empty
res0: scala.collection.immutable.Stream[Option[Option[Option[Int]]]] = Stream(Some(Some(Some(1))), ?)
scala> ~res0.asMA.sum
res1: Option[Option[Int]] = Some(Some(3))
Einige verwandte Fragen
Q. Was ist ein Monoid?
Ein Monoid ist ein Typ M
, für den es eine assoziative binäre Operation (M, M) => M
und ein Identitätselement I
unter dieser Operation gibt, sodass mplus(m, I) == m == mplus(I, m)
für alle m
vom Typ M
Q. Was ist |+|
?
Dies ist nur eine Abkürzung in scalaz (oder ASCII-Wahnsinn, je nachdem) für die mplus
binäre Operation
Q. Was ist ~
?
Es ist ein unärer Operator, der "oder Identität" bedeutet und (unter Verwendung impliziter Konvertierungen von Scala) von der scalaz-Bibliothek für Option[M]
hinzugefügt wird, wenn M
ein Monoid ist. Offensichtlich gibt eine nicht leere Option ihren Inhalt zurück; eine leere Option wird durch das Identitätselement des Monoids ersetzt.
Q. Was ist asMA.sum
?
Ein Foldable
ist im Grunde eine Datenstruktur, über die gefaltet werden kann (wie z.B. foldLeft
). Beachten Sie, dass foldLeft
einen Startwert und eine Operation zur Aneinanderreihung aufeinanderfolgender Berechnungen benötigt. Im Fall des Summierens eines Monoids ist der Startwert das Identitätselement I
und die Operation ist mplus
. Sie können also asMA.sum
auf einem Foldable[M: Monoid]
aufrufen. Möglicherweise müssen Sie asMA
verwenden, um einen Namenskonflikt mit der sum
-Methode der Standardbibliothek zu vermeiden.
Einige Referenzen
- Folien und Video eines Vortrags, den ich gehalten habe, der praktische Beispiele für die Verwendung von Monoiden in der Praxis liefert
2 Stimmen
Du extrahierst den Inhalt der Option nicht auf die richtige Weise. Wenn du Fallentscheidungen wie Some(x) hast, ist x der Wert innerhalb der Option (Typ Int) und du rufst get nicht darauf auf. Fallentscheidungen wie Some(x) => x. Wie auch immer, wenn du den Inhalt oder den Standardwert haben möchtest, ist a.getOrElse(0) bequemer.
0 Stimmen
@didierd DANKE! Das war die Antwort, die ich brauchte. Kannst du es in eine Antwort umwandeln? Ich werde deine wählen.
0 Stimmen
Verpflichtender Verweis: blog.tmorris.net/scalaoption-cheat-sheet