simbolos pattern opciones mundo librerias importar hola hacer ejemplos como haskell

opciones - pattern matching haskell



¿Cuál es el punto de ''const'' en el preludio de Haskell? (6)

Parece que no puedo encontrar nada relevante con respecto a esta función.

Muchas de las otras respuestas discuten aplicaciones relativamente esotéricas (al menos para el recién llegado) de const . Aquí hay uno simple: puede usar const para deshacerse de una lambda que toma dos argumentos, descarta la primera pero hace algo interesante con la segunda.

Por ejemplo, la siguiente implementación (ineficaz) de length ,

length'' = foldr (/_ acc -> 1 + acc) 0

puede ser reescrito como

length'' = foldr (const (1+)) 0

que es quizás más elegante.

La expresión const (1+) es en efecto equivalente a /_ acc -> 1 + acc , porque toma un argumento, lo descarta y devuelve la sección (1+) .

Mirando a través del preludio de Haskell, veo una función const :

const x _ = x

Parece que no puedo encontrar nada relevante con respecto a esta función.

¿Cuál es el punto de? ¿Alguien puede dar un ejemplo de dónde se puede usar esta función?


Es útil para pasar a funciones de orden superior cuando no se necesita toda su flexibilidad. Por ejemplo, el operador de secuencia monádica >> se puede definir en términos del operador de enlace monádico como

x >> y = x >>= const y

Es algo más limpio que usar una lambda

x >> y = x >>= /_ -> y

e incluso puedes usarlo sin puntos

(>>) = (. const) . (>>=)

aunque no lo recomiendo especialmente en este caso.


Otro uso es implementar funciones de miembro de clase que tienen un argumento ficticio que no se debe evaluar (se usa para resolver tipos ambiguos). Ejemplo que podría estar en Data.bits:

instance Bits Int where isSigned = const True bitSize = const wordSize ...

Al usar const decimos explícitamente que estamos definiendo valores constantes.

Personalmente, no me gusta el uso de parámetros ficticios, pero si se usan en una clase, esta es una forma bastante agradable de escribir instancias.


Para agregar a la excelente respuesta directa de hammar: funciones humildes como const e id son realmente útiles como una función de orden superior por la misma razón que son fundamentales en el cálculo del combinador SKI .

No es que crea que las funciones de preludio de Haskell fueron modeladas conscientemente después de ese sistema formal o algo así. Es solo que crear abstracciones ricas en haskell es muy fácil, por lo que a menudo se ve que este tipo de cosas teóricas emergen como prácticamente útiles.

Un plug desvergonzado, pero escribí en mi blog sobre cómo la instancia Applicative para (->) son realmente los combinadores S y K here , si ese es el tipo de cosa que te gusta.


Un ejemplo simple para usar const es Data.Functor.(<$) . Con esta función puedes decir: tengo aquí un functor con algo aburrido, pero en su lugar quiero tener esa otra cosa interesante en él, sin cambiar la forma del funtor. P.ej

import Data.Functor 42 <$ Just "boring" --> Just 42 42 <$ Nothing --> Nothing "cool" <$ ["nonsense","stupid","uninteresting"] --> ["cool","cool","cool"]

La definición es:

(<$) :: a -> f b -> f a (<$) = fmap . const

o escrito no como sin sentido:

cool <$ uncool = fmap (const cool) uncool

Verás cómo se usa const aquí para "olvidarte" de la entrada.


const puede ser solo la implementación que está buscando junto con otras funciones. Aquí hay un ejemplo que descubrí.

Digamos que queremos reescribir una estructura de 2 tuplas a otra estructura de 2 tuplas. Debo expresar esto así:

((a,b),(c,d)) ⇒ (a,(c,(5,a)))

Puedo dar una definición directa con la coincidencia de patrones:

f ((a,b),(c,d)) = (a,(c,(5,a)))

¿Qué pasa si quiero una solución inútil (tácita) para este tipo de reescrituras? Al pensar y manipular más tarde, la respuesta es que podemos expresar cualquier reescritura con (&&&), const, (.), fst, snd . Tenga en cuenta que (&&&) es de Control.Arrow .

La solución del ejemplo que usa estas funciones es:

(fst.fst &&& (fst.snd &&& (const 5 &&& fst.fst)))

Tenga en cuenta la similitud con (a,(c,(5,a))) . ¿Qué pasa si reemplazamos &&& con &&& Luego dice:

(fst.fst, (fst.snd, (const 5, fst.fst)))

Observe cómo a es el primer elemento del primer elemento, y eso es lo que proyecta el fst.fst proyecto. Observe cómo c es el primer elemento del segundo elemento, y eso es lo que proyecta fst.snd . Es decir, las variables se convierten en el camino hacia su origen.

const nos permite introducir constantes. ¡Es interesante cómo el nombre se alinea con el significado!

Luego generalicé esta idea con Applicative para que pueda escribir cualquier función en un estilo sin sentido (siempre que tenga análisis de casos disponibles como funciones, como maybe , bool ). Nuevamente, const juega el papel de introducir constantes. Puede ver este trabajo en el paquete Data.Function.Tacit .

Cuando comienzas de manera abstracta, en la meta, y luego trabajas hacia una implementación, puedes sorprenderte con las respuestas. Es decir, cualquier función puede ser tan misteriosa como cualquier diente en una máquina. Sin embargo, si se retira para ver toda la máquina, puede comprender el contexto en el que es necesario.