2015-12-09 7 views
5

Ich wollte versuchen, Objektive und die Monocle-Bibliothek schien (aus meiner noobish Perspektive) gut mit all diesen schicken ohne Kochplatte @Lenses. Leider habe ich herausgefunden, dass es für Anfänger wenig bis nicht lernfähige Materialien gibt (ich kenne Grundlagen von FP in Vanilla Scala, kein Scalaz). Offizielle Tutorial fehlt einfache Beispiele (und/oder ihre Ergebnisse) und mischt in recht komplexen Scalaz-Bibliothek. Man würde annehmen, dass solch triviale Aufgaben wie der Zugriff auf eine Karte auf einer ersten Seite behandelt werden.Karte ändern über Monocle

Ich habe folgenden Code-Schnipsel:

@Lenses case class House(presentsDelivered: Int) 

    type Houses = Map[(Int, Int), House] 

    @Lenses case class Town(houses: Houses) 

    @Lenses case class Santa(x: Int, y: Int) 

    @Lenses case class World(santa: Santa, town: Town) 

Ich sah at und index, aber keine einfachen Beispiele (nur einig seltsame [Magie für mich] Antwort mit applyOptional den vorformulierten erforderlich). Ich möchte die Karte aktualisieren - houses in Town. Ich habe versucht, etwas in diesem Sinne:

(World.town ^|-> Town.houses ^|-> index((x, y)) ^|-> House.presentsDelivered) 
    .modify { _ + 1 }(world) 

Welche syntaktisch falsch ist, aber ich denke, es ist offensichtlich, was ich (ändern presentsDelivered von House in bestimmten x, y Koordinaten) tun wollte. So ist meine Frage, wie man den index Teil ändert, um auf die Karte zuzugreifen?

Jede Hilfe, Hinweis oder Noob-freundliche Lernmaterialien Tipps sind willkommen.

+1

Entschuldigung für den Mangel an Dokumentation, wir arbeiten langsam daran. Zögern Sie nicht, zu Monokel gitter zu kommen, stellen Sie die Frage hier oder auf github. –

Antwort

7

Sie sind buchstäblich ein Zeichen (und vielleicht ein Import) von der Lösung:

import monocle.function.all.index 
import monocle.std.map._ 

(
    World.town    ^|-> 
    Town.houses    ^|-? 
    index((0, 0))   ^|-> 
    House.presentsDelivered 
).modify(_ + 1) 

Bitte beachte, dass ich die ^|-> sofort ersetzt habe mit ^|-? den Index vorhergehenden. Dies ist notwendig, weil sich index((x, y)) grundlegend von World.town und den anderen Makro-generierten Objektiven für Fallklassenmitglieder unterscheidet. Diese können nicht zeigen auf einen Wert, während index kann fehlschlagen, wenn es keinen Wert bei dem angegebenen Index in der Karte ist. In Bezug auf Monocles Typen ist index((x, y)) ein Optional[Houses, House], während World.town ein Lens[World, Town] ist.

Optionale sind in gewisser Hinsicht schwächer als Objektive, und wenn Sie erst einmal ein Objektiv mit einem optionalen Objektiv komponiert haben, haben Sie weiterhin Optionals, selbst wenn Sie mehr Objektive zusammenstellen. So ist das Folgende eine Linse:

World.town ^|-> Town.houses 

Aber dies ist ein optional:

World.town ^|-> Town.houses ^|-? index((0, 0)) ^|-> House.presentsDelivered 

Monocle x ^|-> y konsequent nutzt verschiedene Arten von x (Linsen, optionals, Querungen, etc.) zu komponieren mit Linsen, und x ^|-? y zu komponieren verschiedene x s mit optionals. Ich persönlich finde die Bediener ein wenig verwirrend und bevorzuge composeLens, composeOptional usw., aber die Geschmäcker variieren, und wenn Sie sich die Bediener merken wollen, können Sie zumindest sicher sein, dass sie konsistent verwendet werden - Sie müssen nur wissen, welche Sie Notwendigkeit für einen bestimmten Typ.

Das andere potenzielle Problem mit Ihrem Code ist, dass Sie dies nicht nur schreiben kann:

import monocle.function.all.index 

val houses: monocle.Optional[Houses, House] = index((0, 0)) 

Dies wird nicht von selbst kompilieren, weil index eine Instanz der für den Typ Index Typklasse erfordert, dass es ist die Indizierung in (in diesem Fall Map[(Int, Int), House] Monocle ein generisches Beispiel für Karten bereitstellt, die funktionieren, aber Sie haben es zu importieren.

import monocle.std.map._ 

ich fürchte, ich habe keine schrecklich gute Vorschläge für learnin g Materialien, aber Sie können hier immer Fragen stellen, und die Monocle Gitter channel ist ziemlich aktiv.

+0

Vielen Dank für eine gründliche und korrekte Antwort. Um ehrlich zu sein, war ich nicht allzu optimistisch, um eine Antwort zu bekommen - nicht sicher, wie beliebt Monocle-Bibliothek ist, aber Tag [Tag: Monokel-Scala] war nicht einmal im zweistelligen Bereich. Ich bin froh, dass ich mich geirrt habe, morgen werde ich etwas Spaß haben, diese [Weihnachtsrätsel] zu lösen (http://adventofcode.com/) :). – monnef