2015-12-09 15 views
5

Chciałem wypróbować soczewki, a biblioteka Monocle wydawała się (z mojej nieobjętej oczyma) dobrą z wszystkimi tymi fantazyjnymi, beznarzędziowymi standardami, @Lenses. Niestety dowiedziałem się, że dla początkujących jest niewiele materiałów do nauki (znam podstawy FP w waniliowej scali, nie ma Scalaza). Oficjalny tutorial nie zawiera łatwych przykładów (i/lub ich wyników) i miesza się w dość skomplikowanej bibliotece Scalaz. Można by przypuszczać, że takie trywialne zadanie, jak dostęp do mapy, zostanie omówione na pierwszej stronie.Modyfikacja mapy za pomocą Monocle

Mam następujący fragment:

@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) 

widziałem at i index, ale ma prostych przykładów (tylko niektóre dziwne [dla mnie] magiczne odpowiedzieć applyOptional których wymagane boilerplate). Chcę zaktualizować mapę - houses w Town. Próbowałam coś w tym duchu:

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

Która jest składniowo źle, ale myślę, że jest oczywiste, co chciałem zrobić (modyfikować presentsDelivered z House w określonych x, y współrzędnych). Moje pytanie brzmi: jak zmodyfikować część index, aby uzyskać dostęp do mapy?

Każda pomoc, wskazówki czy wskazówki dotyczące materiałów do nauki są mile widziane.

+1

Przepraszamy za brak dokumentacji, powoli nad nią pracujemy. Proszę nie wahaj się wyskoczyć do monoklowej gitter, zadaj pytanie tutaj lub na github. –

Odpowiedz

7

Jesteś dosłownie jeden znak (a może import) od rozwiązania:

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

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

Zauważ, że ja zastąpiła ^|-> bezpośrednio poprzedzający indeks z ^|-?. Jest to konieczne, ponieważ index((x, y)) zasadniczo różni się od World.town i innych soczewek generowanych przez makro dla członków klas przypadków. Te nie mogą wskazywać na wartość, podczas gdy index może zawieść, jeśli nie ma wartości w danym indeksie na mapie. Pod względem typów Monocle, index((x, y)) jest Optional[Houses, House], natomiast World.town jest Lens[World, Town].

Opcjonalnie są słabsze niż soczewki, a po skomponowaniu obiektywu z opcją, nadal będziesz mieć opcje, nawet jeśli skomponujesz więcej soczewek. Więc po to obiektyw:

World.town ^|-> Town.houses 

Ale to jest opcjonalny:

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

Monocle konsekwentnie używa x ^|-> y komponować różne rodzaje x (obiektywy, OPCJE, przechodzenia przez, etc.) z obiektywami, i x ^|-? y do komponowania różnych x s z opcjami. Osobiście uważam, że operatorzy są trochę zagmatwani i wolą composeLens, composeOptional itp., Ale smaki są różne, a jeśli chcesz zapamiętywać operatorów, możesz przynajmniej mieć pewność, że są konsekwentnie używane - musisz tylko wiedzieć, który z nich potrzeba danego typu.

Drugi potencjalny problem z kodem jest to, że nie można po prostu napisać to:

import monocle.function.all.index 

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

To nie będzie kompilować na własną rękę, ponieważ index wymaga instancję klasy Index typu dla typu, który to do indeksowania (w tym przypadku Map[(Int, Int), House] Monocle zapewnia ogólny instancję dla map, które będą działać, ale trzeba go importować.

import monocle.std.map._ 

Obawiam się, że nie mają żadnych strasznie dobre propozycje dla learnin g materiałów, ale zawsze możesz zadawać pytania tutaj, a Monocle Gitter channel jest dość aktywny.

+0

Dziękuję za dokładną i poprawną odpowiedź. Szczerze mówiąc, nie byłem zbyt optymistycznie nastawiony, aby uzyskać odpowiedź - nie jestem pewny, jak popularna jest biblioteka Monocle, ale tag [tag: monocle-scala] nie był nawet dwucyfrowy. Cieszę się, że się myliłem, jutro będę się dobrze bawić rozwiązując te [zagadki świąteczne] (http://adventofcode.com/) :). – monnef