2014-11-01 6 views
8

Voglio convertire questa riga di codice map (^?! ix 0) [[0, 1], [4, 5], [9, 1]] per utilizzare interamente obiettivi, quindi qualcosa come [[0, 1], [4, 5], [9, 1]] & each . ix 0. Tuttavia, i tipi non corrispondono. Qual è il modo corretto per farlo?Usa obiettivo come `mappa`

risposta

10

Uso folded:

Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. folded . ix 0 
[0,4,9] 

Funziona su qualsiasi Foldable.

Inoltre, se si pianifica di estrarre sempre il primo elemento, forse sarebbe più chiaro utilizzare l'attraversamento _head da Control.Lens.Cons anziché ix.

[[0, 1], [4, 5], [9, 1]] ^.. folded . _head 
10

È possibile utilizzare uno dei

Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] & each %~ (^?! ix 0) 
[0,4,9] 
Prelude Control.Lens> [[0, 1], [4, 5], [9, 1]] ^.. each . ix 0 
[0,4,9] 

Il primo corrisponde precisamente quello che hai scritto, utilizzando il pericoloso (^?!) dell'operatore, il che significa che può dare un errore. Il secondo è più sicuro tralasciando le liste vuote.

Lavorano in modi diversi: il primo crea una versione modificata della struttura originale, che corrisponde più a ciò che fa map e può essere utilizzata su strutture che non sono elenchi.

Il secondo crea un sommario dell'elenco della struttura utilizzando la piegatura dell'obiettivo fornita; sebbene possa essere utilizzato con molti tipi di strutture, il risultato è sempre un elenco.

È inoltre possibile sostituire each per traverse (o, come @danidiaz sottolinea, il leggermente più generale traversed) in questo. Il primo funziona per molte cose speciali come le tuple, mentre il secondo funziona per qualsiasi Traversable.

+1

Forse intendete "attraversato" da "Control.Lens.Traversal', invece di" traverse "? – danidiaz

+2

@danidiaz No, intendo "traverse". Sebbene non sia * dall'obiettivo *, è considerato una parte essenziale di esso. –

+0

@danidiaz Oh capisco, * entrambi * lavorano qui. Sembra "attraversato" è più generale, consentendo indici. –