Monads Flashcards
Was ist ein Monad?
- Ein funktionales Design Pattern
- Ein Container für eine algebraische Datenstruktur z.b. Monoid
Was ist ein Monoid?
Algebraische Struktur mit einer assoziativen binären Operation und einem identifizierenden Element
Welche Regeln gelten für Monoids?
- Assoziativität: (a*b)*c=a*(b*c)
- Identifizierendes Element: Es gibt ein Element e in S für das jedes Element a in S gilt: e * a = a * e = a
Beispiele für Monoiden
- String mit concat und leerem String
- Integer mit add und 0
Funktionsweise Monad und Monoid?
- Wir nehmen ein Monoid aus dem Container (Monad)
- Führen eine Operation auf dem Monoid aus
- Fügen das Monoid in einen neuen Container ein
Sind Option und Try Monaden oder Monoiden?
Monaden
Warum ist Option ein Monad?
Option kann Some() oder None enthalten (Container leer oder befüllt)
Warum ist Try ein Monad?
Try kann Success oder Failure enthalten (Flasche ganz, Flasche kaputt)
Welchem Pattern ähnelt ein Monad?
Dem State Pattern
Unterschied Monad zu Monoid?
Monad: Unterscheidet guten und schlechten Fall
Monoid: Konvertiert von einem Set in das gleiche Set
Beispiel für One Track Code
object BottleState extends Enumeration { type BottleState = Value val Empty, Labeled, Filled, Capsuled, Consumed = Value } import BottleState._
case class Bottle(state: BottleState = Empty) {
def label: Bottle = copy(state= Labeled)
def fill:Bottle = copy(state= Filled)
def capsule:Bottle = copy(state= Capsuled)
def consume:Bottle = {
println(“ consuming… “)
copy(Consumed)
}
}
~~~
new Bottle().label.fill.capsule
~~~
Beispiel für Two Track Code
case class MaybeBottle(bottle: Option[Bottle]) { def label : MaybeBottle = bottle match { case Some(bottle:Bottle) => copy( Some(bottle.label)) case None => copy(None) } def fill: MaybeBottle = bottle match { case Some(bottle:Bottle) => copy( Some(bottle.fill)) case None => copy(None) } def capsule: MaybeBottle = bottle match { case Some(bottle:Bottle) => copy( Some(bottle.capsule)) case None => copy(None) } } MaybeBottle(Some(new Bottle)).label.fill.capsule MaybeBottle(None).label.fill.capsule
Wie entpackt man Monads?
Durch for-comprehensions: for (x <- e1) yield toValue(x)
Monad:
for (bottle <- pack.bottles) yield bottle match { case Some(b) => b.consume case None => println("Found None") }