Facciamo un gioco. Ci sono due pile che useremo, entrambe costituite da chip con lati neri/bianchi.Aggiornamento di più sottocampi di un campo usando l'obiettivo di ekmett
data Pile = Pile { _blacks, _whites :: Int }
makeLenses ''Pile
data Game = Game { _pileA, _pileB :: Pile }
makeLenses ''Game
Davvero un mossa intelligente sarebbe quella di girare un chip nero in pile A, e un chip bianco - in pile B. Ma come?
cleverMove :: Game -> Game
cleverMove game = game & pileA . blacks -~ 1
& pileA . whites +~ 1
& pileB . blacks +~ 1
& pileB . whites -~ 1
Non molto elegante. Come posso farlo senza fare riferimento a ciascuna pila due volte?
L'unica cosa che mi è venuta (e non mi piace):
cleverMove game = game & pileA %~ (blacks -~ 1)
. (whites +~ 1)
& pileB %~ (blacks +~ 1)
. (whites -~ 1)
(Spiacente in anticipo se è ovvio - Sono un po 'nuova per lenti e mi sento perso in mare di combinatori e operatori lens
offerte. c'è probabilmente tutto per è mai stato così nascosto lì. Non che sia male, naturalmente! ma mi piacerebbe che ci fosse anche un manuale completo incluso.)
Cosa non ti piace dell'opzione 2? Non può essere molto più conciso di così, vero? – leftaroundabout
@leftaroundabout Non mi piace che ho dovuto usare parentesi, che diventano maldestre quando sono coinvolte espressioni multilinea - come ad esempio blocchi 'do' e ulteriori livelli di nidificazione. – Artyom
Penso che sarebbe d'aiuto se mostrassi qualche pseudo-codice approssimativo corrispondente a come sarebbe la tua sintassi ideale. –