No entiendo lo que es "levantar". ¿Debería primero entender las mónadas antes de entender qué es un "ascensor"? (Igualmente, soy completamente ignorante sobre las mónadas :) ¿O alguien puede explicarme con palabras simples?¿Qué es "levantar" en Haskell?
Respuesta
La elevación es más un patrón de diseño que un concepto matemático (aunque espero que alguien por aquí ahora me refute al mostrar cómo los ascensores son una categoría o algo así).
Normalmente tiene algún tipo de datos con un parámetro. Algo así como
data Foo a = Foo { ...stuff here ...}
Supongamos que usted encuentra que una gran cantidad de usos de Foo
tomar tipos numéricos (Int
, Double
etc) y te guarde tener que escribir código que se desenvuelve estos números, añade o los multiplica, y luego las envuelve la espalda arriba. Puede cortocircuitar esto escribiendo el código desenvolver y envolver una vez. Esta función se llama tradicionalmente "levantar" porque se parece a esto:
liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
En otras palabras, usted tiene una función que toma una función de dos argumentos (como el operador (+)
) y lo convierte en la función equivalente para Foos.
lo que ahora puede escribir
addFoo = liftFoo2 (+)
Editar: más información
Por supuesto, puede tener liftFoo3
, liftFoo4
y así sucesivamente. Sin embargo, esto a menudo no es necesario.
de inicio con la observación
liftFoo1 :: (a -> b) -> Foo a -> Foo b
Pero eso es exactamente lo mismo que fmap
.Así que en lugar de liftFoo1
que iba a escribir
instance Functor Foo where
fmap foo = ...
Si realmente desea la regularidad completa a continuación, puede decir
liftFoo1 = fmap
Si se puede hacer Foo
en un funtor, tal vez puede que sea un funtor aplicativo. De hecho, si se puede escribir liftFoo2
entonces la instancia aplicativo se parece a esto:
import Control.Applicative
instance Applicative Foo where
pure x = Foo $ ... -- Wrap 'x' inside a Foo.
(<*>) = liftFoo2 ($)
El operador (<*>)
de Foo tiene el tipo
(<*>) :: Foo (a -> b) -> Foo a -> Foo b
Se aplica la función ajustada al valor ajustado. Entonces, si puede implementar liftFoo2
, puede escribir esto en términos de ello. O se puede aplicar directamente y no molestarse en liftFoo2
, ya que el módulo incluye Control.Applicative
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
e igualmente hay liftA
y liftA3
. Pero en realidad no se utiliza muy a menudo porque no hay otro operador
(<$>) = fmap
Esto le permite escribir:
result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
El término myFunction <$> arg1
devuelve una nueva función envuelto en Foo. Esto a su vez se puede aplicar al siguiente argumento usando (<*>)
, y así sucesivamente. Así que ahora, en lugar de tener una función de elevación para cada aria, solo tienes una cadena de aplicativos.
Probablemente valga la pena recordar que los ascensores deben respetar las leyes estándar 'lift id == id' y' lift (f. G) == (lift f). (levantar g) '. –
Los elevadores son de hecho "una categoría o algo". Carlos acaba de enumerar las leyes de Functor, donde 'id' y' .' son la flecha de identidad y la composición de flecha de alguna categoría, respectivamente. Por lo general, cuando se habla de Haskell, la categoría en cuestión es "Hask", cuyas flechas son funciones Haskell (en otras palabras, 'id' y' .' se refieren a las funciones Haskell que conoces y amas). –
me gusta la forma en que empiezas mencionando un tipo con un parámetro. Esta es la idea más importante sobre Monad. Todavía no puedo creer que en el libro: Haskell mundo real del autor ni de explicar que Mónada es simplemente una clase de tipo (ver el capítulo sobre las mónadas y la programación mónada en ese libro) – osager
de elevación es un concepto que permite transformar una función en una función correspondiente dentro de otro (por lo general más general) establecer
echar un vistazo a http://haskell.org/haskellwiki/Lifting
Sí, pero esa página comienza "Normalmente comenzamos con un functor (covariante) ...". No es exactamente amiga de los novatos. –
Pero el "functor" está vinculado, por lo que el novato solo puede hacer clic para ver qué es un Functor. Es cierto que la página vinculada no es tan buena. Necesito obtener una cuenta y arreglar eso. – jrockway
Es un problema que he visto en otros sitios de programación funcional; cada concepto se explica en términos de otros conceptos (desconocidos) hasta que el novato da un rodeo completo (y alrededor de la curva). Debe tener algo que ver con que te guste la recursión. – DNA
Vamos a empezar con un ejemplo:
> replicate 3 'a'
"aaa"
> :t replicate
replicate :: Int -> a -> [a]
> :t liftA2 replicate
liftA2 replicate :: (Applicative f) => f Int -> f a -> f [a]
> (liftA2 replicate) [1,2,3] ['a','b','c']
["a","b","c","aa","bb","cc","aaa","bbb","ccc"]
> :t liftA2
liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
liftA2
transforma en función de los tipos de fricción a una función de estos tipos envueltos en una Applicative
, tales como listas, IO
, etc.
Otro ascensor común es lift
de Control.Monad.Trans
. Transforma una acción monádica de una mónada a una acción de una mónada transformada.
En general, levanta "levantar" una función/acción en un tipo "envuelto".
La mejor manera de entender esto, y las mónadas, etc. y comprender por qué son útiles, es probablemente para codificarlo y usarlo. Si hay algo que codificaste previamente que sospechas puede beneficiarse de esto (es decir, esto acortará el código, etc.), simplemente pruébalo y entenderás fácilmente el concepto.
Paul's y yairchu son buenas explicaciones.
Me gustaría agregar que la función que se está levantando puede tener un número arbitrario de argumentos y que no tienen que ser del mismo tipo. Por ejemplo, también se puede definir un liftFoo1:
liftFoo1 :: (a -> b) -> Foo a -> Foo b
En general, el levantamiento de las funciones que toman 1 argumento es capturado en la clase de tipo Functor
, y la operación de elevación se llama fmap
:
fmap :: Functor f => (a -> b) -> f a -> f b
Tenga en cuenta la similitud con el tipo liftFoo1
. De hecho, si usted tiene liftFoo1
, puede hacer Foo
una instancia de Functor
:
instance Functor Foo where
fmap = liftFoo1
Por otra parte, la generalización de levantar a un número arbitrario de argumentos se llama estilo aplicativo. No se moleste en sumergirse en esto hasta que capte el levantamiento de las funciones con un número fijo de argumentos. Pero cuando lo haces, Learn you a Haskell tiene un buen capítulo sobre esto. El Typeclassopedia es otro buen documento que describe Functor y Aplicable (así como otras clases de tipos, vaya al capítulo de la derecha en ese documento).
Espero que esto ayude!
Según this shiny tutorial, un funtor es un poco de contenedor (como Maybe<a>
, List<a>
o Tree<a>
que puede almacenar elementos de algunos otro tipo, a
). He utilizado Java genéricos notación, <a>
, para el elemento de tipo a
y pensar en los elementos como las bayas en el árbol Tree<a>
. Hay una función fmap
, que tiene una función de conversión de elemento, a->b
y el recipiente functor<a>
. Aplica a->b
a cada elemento del contenedor convirtiéndolo efectivamente en functor<b>
. Cuando se suministra sólo primer argumento, a->b
, fmap
espera a que el functor<a>
. Es decir, el suministro de a->b
solo convierte esta función a nivel de elemento en la función de functor<a> -> functor<b>
que opera sobre los contenedores. Esto se llama levantando de la función. Debido a que el recipiente también se llama un funtor , los Functors en lugar de las mónadas son un requisito previo para el levantamiento. Las mónadas son una especie de "paralelo" al levantamiento. Ambos se basan en la noción de Functor y hacen f<a> -> f<b>
. La diferencia es que la elevación usa a->b
para la conversión, mientras que Monad requiere que el usuario defina a -> f<b>
.
Les di una marca, porque "un functor es un contenedor" es cebo de llama con sabor a troll. Ejemplo: funciones de algún 'r' a un tipo (usemos' c' para variedad), son Functors. No "contienen" ninguna 'c'. En este caso, fmap es la composición de la función, tomando una función 'a -> b' y una' r -> a', para darle una nueva función 'r -> b'. Todavía no hay contenedores. También, si pudiera, lo volvería a marcar para la oración final. – BMeph
Además, 'fmap' es una función y no" espera "nada; El "contenedor" es un Functor es el punto de levantamiento. Además, las mónadas son, en todo caso, una idea doble para levantar: una mónada le permite usar algo que se ha levantado algunas veces positivas, como si solo se hubiera levantado una vez; esto es mejor conocido como _flattening_. – BMeph
@BMeph 'Esperar',' esperar', 'anticipar' son los sinónimos. Al decir "función espera" quise decir "función anticipada". – Val
- 1. ¿Qué es esta sintaxis haskell?
- 2. ¿Qué es un patrón anidado en Haskell?
- 3. ¿Qué es una "chispa" en Haskell
- 4. ¿Qué es [] (constructor de lista) en Haskell?
- 5. ¿Qué significa ': ..' en Haskell?
- 6. Haskell - ¿Qué es Control.Applicative.Alternative good for?
- 7. ¿Por qué Haskell es tan grande?
- 8. ¿Qué es Stream Fusion de Haskell?
- 9. Levantar eventos personalizados en C# WinForms
- 10. ¿Qué significa `~` en Haskell?
- 11. Cómo levantar eventos usando addHandler
- 12. Python: ¿es mala forma levantar excepciones dentro de __init__?
- 13. ¿Por qué levantar una tupla funciona si el primer elemento es una excepción?
- 14. ¿Qué significa apóstrofo en Haskell?
- 15. Sintaxis ¿Qué significa $$ en Haskell?
- 16. nombres ADT. ¿Qué es `Left a`, y luego, ¿qué es` a` en Haskell?
- 17. Haskell: ascensor vs liftIO
- 18. Haskell: ¿Es un desastre?
- 19. KeyErrors y cómo levantar un KeyError
- 20. Levantar eventos de clase base en clases derivadas C#
- 21. ¿Por qué esta expresión de Haskell es tan lenta?
- 22. Coincidencia de patrones de Haskell: ¿qué es eso?
- 23. ¿Por qué es tan simple este algoritmo haskell tan lento?
- 24. ¿Qué hace el operador: infijo en Haskell?
- 25. Instancia de clase de elevación en Haskell
- 26. PCRE en Haskell: ¿qué, dónde, cómo?
- 27. ¿Qué analizador XML para Haskell?
- 28. ¿Qué significa :: (doble colon) en Haskell?
- 29. ¿Qué significa el símbolo => en Haskell?
- 30. ¿Cómo cambiar un paquete raíz del proyecto Levantar?
Quizás útil, tal vez no: http://www.haskell.org/haskellwiki/Lifting – kennytm