2014-05-14 11 views
5

Questa è una domanda trival.Come mappare una funzione sugli elementi di un elenco annidato

Ma qual è il modo standard per mappare una funzione (+1 in questo esempio) nell'elenco nidificato?

map (\x -> map (+1) x) [[1,2,3],[4,5,6]] 

Uso il metodo di cui sopra nel mio codice, ma quale è un buon modo per farlo? C'è qualcosa come un mapNested (+1) [[1,2,3],[4,5,6]] o simile? Ho usato google e hoogle ma ho ottenuto risultati troppo generici.

+0

Se vuoi, puoi definire 'mapNested f xs = map (\ x -> map f x) xs'. Ma il modo in cui lo fai è il modo canonico, se escludiamo alcune convenzioni tipografiche. – kqr

risposta

14

Ci sono alcuni modi, ma il più evidente è:

Prelude> map (map (+1)) [[1,2,3],[4,5,6]] 
[[2,3,4],[5,6,7]] 

Questa sarebbe la risposta da manuale.

Forse ti piace fare la parte esterna con una lista di comprensione?

Prelude> [ map (+1) xs | xs <- [[1,2,3],[4,5,6]] ] 
[[2,3,4],[5,6,7]] 

O anche il tutto?

Prelude> [ [ x + 1 | x <- xs ] | xs <- [[1,2,3],[4,5,6]] ] 
[[2,3,4],[5,6,7]] 
3

È necessario composizione delle mappe: (map . map) (+1) [[1,2,3],[4,5,6]]

9

Non credo che definito in qualsiasi parte della libreria standard, ma è possibile definire come tale:

mapNested :: (a -> b) -> [[a]] -> [[b]] 
mapNested = map . map 

O per renderlo più generico (vale a dire lavorare su altri functors di liste.):

fmapNested :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) 
fmapNested = fmap . fmap 

uso Esempio:

fmapNested (+1) [Some 1, None, Some 3] -- == [Some 2, None, Some 4] 
+0

È davvero "il più generico possibile"? Voglio dire ... 'incEverything = everywhere (mkT ((+1) :: Int -> Int))' e poi 'incEverything [[Just 3, Just 54, Nothing] :: [Maybe Int]] ~~> [ [Solo 4, Solo 55, Niente]] –

+2

Mentre è equivalente a 'fmap. fmap', potresti invece scrivere 'fmap fmap fmap' per questa operazione. È equivalente perché il primo 'fmap' viene applicato al functor' (->) r', che diventa solo composizione. È un'astrazione piuttosto divertente, però, e ti permette di mappare questo calcolo annidato a 2 strati in profondità in qualsiasi due funzioni. È anche equivalentemente il '(. :) = (.). (.) 'Operatore ma più generalizzato. – bheklilr

+1

Lezione appresa: mai dire "il più generico possibile" in Haskell, o qualcuno * ti darà un esempio ancora più generico :) – Tarmil

Problemi correlati