¿Qué hace concatMap
? Sé lo que concat
y map
do. ¿Están ambos juntos o es una función completamente diferente?¿Qué hace concatMap?
Respuesta
Conceptualmente sí, pero el actual implementation es diferente:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = foldr ((++) . f) []
Podría ser útil indicar por qué 'concatMap' se implementa con' foldr', siendo el motivo cortar la deforestación usando la técnica 'foldr/build': https://ghc.haskell.org/trac/ghc/wiki/FoldrBuildNotes –
Comprobación the documentation revela:
concatMap :: (a -> [b]) -> [a] -> [b]
mapear una función sobre una lista y concatenar los resultados
Y que su definición es así:
-- | Map a function over a list and concatenate the results.
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = foldr ((++) . f) []
comparar la siguiente salida de ghci:
*Main> concatMap (++"! ") ["one", "two", "three"]
"one! two! three! "
*Main> concat $ map (++"! ") ["one", "two", "three"]
"one! two! three! "
Además, si se está preguntando * por qué * existe, creo que es porque es la implementación de la lista de '>> =', acaba de dar un nombre diferente. :) – porges
Sí, la función concatMap
es sólo concat
y map
juntos. De ahí el nombre. Poner juntas las funciones simplemente significa componer:
(.) :: (b -> c) -> (a -> b) -> a -> c
Sin embargo concat
y map
no se pueden poner juntos por el simple uso de la composición de funciones debido a la firma de tipo de map
:
map :: (a -> b) -> [a] -> [b]
-------- --- ---
a b c
Como se puede ver la composición de funciones espera una función del tipo a -> b
, pero map
es del tipo a -> b -> c
.Para componer concat
con map
es necesario utilizar el operador .:
lugar:
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
La función concat
tiene una firma tipo de:
concat :: [[a]] -> [a]
----- ---
c d
Por lo tanto concat .: map
es de tipo:
concat .: map :: (a -> [b]) -> [a] -> [b]
---------- --- ---
a b d
Que es el mismo que el de concatMap
:
concatMap :: (a -> [b]) -> [a] -> [b]
El operador .:
sí se puede escribir en términos de composición de funciones:
(.:) = (.) (.) (.)
-- or
(.:) = (.) . (.)
Por lo tanto concatMap
se puede escribir como:
concatMap = (.) (.) (.) concat map
-- or
concatMap = (concat .) . map
-- or
concatMap = concat .: map
Si usted flip
los argumentos de concatMap
se obtiene el >>=
(enlace) función de la lista mónada:
instance Monad [] where
return x = [x]
(>>=) = flip concatMap
fail _ = []
flip concatMap :: [a] -> (a -> [b]) -> [b]
>>= :: Monad m => m a -> (a -> m b) -> m b
Esto hace que sea la misma que la función de la lista =<<
mónada:
concatMap :: (a -> [b]) -> [a] -> [b]
=<< :: Monad m => (a -> m b) -> m a -> m b
Así que ya saben todo lo que hay que saber sobre concatMap
. Solo se aplica concat
al resultado de map
. De ahí el nombre.
Excelente respuesta. Solo un error tipográfico: "** En ** volteas [...]" debería ser ** Si **. – YoTengoUnLCD
- 1. ¿Qué hace [:]?
- 2. ¿Por qué hace esto lo que hace?
- 3. ¿Qué hace CreateFile ("CONIN $" ..)?
- 4. DefaultMemberAttribute: ¿qué hace?
- 5. ¿Qué hace document.domain = document.domain?
- 6. ¿Qué hace un IISReset?
- 7. ¿Qué hace "mro()"?
- 8. ¿Qué hace sp_tablecollations_100?
- 9. ¿Qué hace esta función?
- 10. ¿Qué hace "file.sync = true"?
- 11. ¿Qué hace pg_escape_string exactamente?
- 12. ¿Qué hace testAndroidTestCaseSetUpProlyly
- 13. ¿Qué hace L?
- 14. ¿Qué hace "<%:" hacer?
- 15. ¿Qué hace realmente BlockingCollection.Dispose?
- 16. ¿Qué hace HTML.Raw?
- 17. HttpWebRequest.UserAgent: ¿Qué hace?
- 18. DataGridView: ¿qué hace AllowUserToAddRows?
- 19. ¿Qué hace System.Concurrency.AsyncLock?
- 20. ¿Qué hace ReDim Preserve?
- 21. ¿Qué hace APIENTRY?
- 22. ¿Qué hace IFormatProvider?
- 23. ¿Qué hace -XX: MaxPermSize?
- 24. ¿Qué hace mmap?
- 25. ¿Qué hace waitpid()?
- 26. ¿Qué hace Html.HiddenFor?
- 27. Android - ¿Qué hace adapter.notifyDataSetInvalidated?
- 28. ¿qué hace mysql_real_escape_string() realmente?
- 29. ¿Qué hace realmente "OperationContext.Current.GetCallbackChannel"?
- 30. ¿Qué hace el @sign?
Comportamentalmente no se puede distinguir de 'concatMap f = concat. mapa f'. No estoy seguro de que sea teóricamente más eficiente tampoco. Es solo una combinación conveniente, supongo. – luqui
@luqui Como 'concatMap' se implementa mediante' foldr', se puede optimizar utilizando la técnica 'foldr/build'. Por lo tanto, sí, es más eficiente: https://ghc.haskell.org/trac/ghc/wiki/FoldrBuildNotes –