sensibles partes para mapa las imagenes imagen hacer emplea elementos ejemplos ejemplo definir coords como atributo activas haskell

partes - ¿Cuál es el objetivo del mapa en Haskell, cuando hay fmap?



mapa de atributo (3)

En todas partes que he intentado usar map , fmap ha funcionado. ¿Por qué los creadores de Haskell sintieron la necesidad de una función de map ? ¿No podría ser simplemente lo que actualmente se conoce como fmap y fmap podría eliminarse del lenguaje?


Citando de la documentación de Functor en https://wiki.haskell.org/Typeclassopedia#Functor

Puede preguntar por qué necesitamos una función de map separado. ¿Por qué no acaba con la función de map actual de solo lista y cambia el nombre de fmap al map ? Bueno, esa es una buena pregunta. El argumento habitual es que alguien que acaba de enterarse de Haskell, al usar el map incorrectamente, preferiría ver un error sobre listas que sobre Functor .


Me gustaría hacer una respuesta para llamar la atención sobre el comentario de augustss :

De hecho, no es así como sucede. Lo que sucedió fue que el tipo de mapa se generalizó para cubrir a Functor en Haskell 1.3. Es decir, en Haskell 1.3 fmap se llamaba mapa. Este cambio se revirtió en Haskell 1.4 y se introdujo fmap. La razón de este cambio fue pedagógica; al enseñar Haskell a los principiantes, el tipo muy general de mapa hacía que los mensajes de error fueran más difíciles de entender. En mi opinión, esta no era la forma correcta de resolver el problema.

Haskeller 98 es visto como un paso atrás por algunos Haskellers (incluyéndome a mí), las versiones anteriores habían definido una biblioteca más abstracta y consistente. Oh bien.


Se ven iguales en el sitio de la aplicación, pero son diferentes, por supuesto. Cuando aplique cualquiera de esas dos funciones, map o fmap , a una lista de valores, producirán el mismo resultado, pero eso no significa que sean para el mismo propósito.

Ejecute una sesión GHCI (el Compilador de Haskell de Glasgow interactivo) para consultar información sobre esas dos funciones, luego eche un vistazo a sus implementaciones y descubrirá muchas diferencias.

mapa

Consultar GHCI para obtener información sobre el map

Prelude> :info map map :: (a -> b) -> [a] -> [b] -- Defined in ‘GHC.Base’

y verá que se define como una función de orden superior aplicable a una lista de valores de cualquier tipo que arroje una lista de valores de cualquier tipo b . Aunque polimórfica (la a y la b en la definición anterior representan cualquier tipo), la función del map está destinada a ser aplicada a una lista de valores que es solo un tipo de datos posible entre muchos otros en Haskell. La función de map no se pudo aplicar a algo que no es una lista de valores.

Como puede leer en el código fuente de GHC.Base , la función de map se implementa de la siguiente manera

map _ [] = [] map f (x:xs) = f x : map f xs

que hace uso de la coincidencia de patrones para sacar la cabeza (la x ) de la cola (la xs ) de la lista, luego construye una nueva lista usando el constructor de valores : (cons) para anteponer a fx ( fx como "f aplicado x ) a la recursión del map sobre la cola hasta que la lista esté vacía. Vale la pena observar que la implementación de la función de map no se basa en ninguna otra función, sino solo en sí misma.

fmap

Ahora intenta buscar información sobre fmap y verás algo bastante diferente.

Prelude> :info fmap class Functor (f :: * -> *) where fmap :: (a -> b) -> f a -> f b ... -- Defined in ‘GHC.Base’

Esta vez, fmap se define como una de las funciones cuyas implementaciones deben proporcionar los tipos de datos que desean pertenecer a la clase de tipo Functor . Eso significa que puede haber más de un tipo de datos, no solo el tipo de datos "lista de valores" , que pueden proporcionar una implementación para la función fmap . Eso hace que fmap sea ​​aplicable a un conjunto mucho mayor de tipos de datos: ¡los funtores de verdad!

Como puede leer en el código fuente de GHC.Base , una posible implementación de la función fmap es la proporcionada por el tipo de datos Maybe :

instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)

y otra implementación posible es la proporcionada por el tipo de datos de 2 tuplas

instance Functor ((,) a) where fmap f (x,y) = (x, f y)

y otra posible implementación es la proporcionada por el tipo de datos de lista (¡por supuesto!):

instance Functor [] where fmap f xs = map f xs

que se basa en la función de map (tenga en cuenta la notación sin puntos allí ... pero eso está fuera del alcance de su pregunta original).

Conclusión

La función de map se puede aplicar a nada más que una lista de valores (donde los valores son de cualquier tipo) mientras que la función fmap se puede aplicar a muchos más tipos de datos: todos los que pertenecen a la clase de functor (por ejemplo, maybes, tuplas, listas, etc.). Dado que el tipo de datos "lista de valores" también es un funtor (porque proporciona una implementación para él), a continuación, puede aplicarse fmap y produce el mismo resultado que el map .

map (+3) [1..5] fmap (+3) (Just 15) fmap (+3) (5, 7)