2015-12-09 12 views
5

Volevo provare gli obiettivi e la libreria Monocle sembrava (dal mio punto di vista noobish) buona con tutti quei fantasiosi piatti senza @Lenses. Sfortunatamente ho scoperto che ci sono pochi materiali non di apprendimento per principianti (conosco le basi del FP in Vanilla Scala, senza Scalaz). Il tutorial ufficiale manca di semplici esempi (e/o dei loro risultati) e si mescola in una libreria Scalaz piuttosto complessa. Si potrebbe supporre che un'attività così banale come l'accesso a una mappa sia coperta da una prima pagina.Modifica mappa tramite Monocle

devo seguente frammento:

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

ho visto at e index, ma non semplici esempi (solo qualche strano [magici per me] Rispondere con applyOptional che ha richiesto boilerplate). Voglio aggiornare la mappa - houses in Town. Stavo cercando qualcosa in questo spirito:

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

Quale è sintatticamente sbagliato, ma credo che sia evidente quello che volevo fare (modifica presentsDelivered di House a specifici x, y coordinate). Quindi la mia domanda è, come modificare la parte index per accedere alla mappa?

Qualsiasi suggerimento sui materiali didattici di aiuto, indizio o noob-friendly è benvenuto.

+1

Siamo spiacenti per la mancanza di documentazione, stiamo lentamente lavorando su di esso. Per favore non esitare a fare un salto a monocle gitter, fare domande qui o su github. –

risposta

7

Sei letteralmente un carattere (e forse un import) lontano dalla soluzione:

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

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

Nota che ho sostituito il ^|-> immediatamente precedente l'indice con ^|-?. Ciò è necessario perché index((x, y)) è fondamentalmente diverso da World.town e gli altri obiettivi generati da macro per i membri della classe case. Quelle non possono non puntare a un valore, mentre index non può riuscire se non c'è alcun valore nell'indice specificato nella mappa. In termini di tipi di Monocle, index((x, y)) è un Optional[Houses, House], mentre World.town è un Lens[World, Town].

Gli optionals sono più deboli in un certo senso degli obiettivi, e una volta composto un obiettivo con un optional, continuerai ad avere opzionali anche se componi più obiettivi. Così il seguente è un obiettivo:

World.town ^|-> Town.houses 

Ma questo è un optional:

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

Monocle utilizza in modo coerente x ^|-> y per comporre diversi tipi di x (lenti, optionals, attraversamenti, ecc) con le lenti, e x ^|-? y per comporre diversi x s con opzioni. Personalmente trovo gli operatori un po 'confusi e preferisco composeLens, composeOptional, ecc., Ma i gusti variano, e se vuoi memorizzare gli operatori puoi almeno essere sicuro che siano usati in modo coerente - devi solo sapere quale bisogno di un dato tipo

L'altro potenziale problema con il codice è che non si può semplicemente scrivere questo:

import monocle.function.all.index 

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

Questo non verrà compilato da solo perché index richiede un'istanza della classe Index tipo per il tipo che è l'indicizzazione in (in questo caso Map[(Int, Int), House] Monocle fornisce un esempio generico per le mappe che funzionerà, ma è necessario importarlo:.

import monocle.std.map._ 

Temo di non avere alcun terribilmente buoni suggerimenti per learnin g materiali, ma puoi sempre fare domande qui, e il Monocle Gitter channel è abbastanza attivo.

+0

Grazie per una risposta accurata e corretta. Ad essere onesti, non ero troppo ottimista sull'ottenere una risposta - non sono sicuro di quanto sia popolare la libreria di Monocle, ma il tag [tag: monocle-scala] non era nemmeno a due cifre. Sono contento di aver sbagliato, domani mi divertirò un mondo a risolvere quei [puzzle di Natale] (http://adventofcode.com/) :). – monnef

Problemi correlati