expresiones Lambda sin parámetros en el cálculo de Haskell y / o lambda

7

En lenguajes ansiosos como Scheme y Python, puedes usar una expresión lambda sin parámetros para retrasar la evaluación, por ejemplo. en Esquema (Esquema de pollo):

#;1> (define (make-thunk x) (lambda () (+ x 1)))
#;2> (define t (make-thunk 1))
#;3> (t)
2

En la línea 2, t está vinculado a la expresión no evaluada (lambda () (+ 1 1)) , que luego se evalúa como 2 en la línea 3.

Del mismo modo, en Python:

>>> def make_thunk(x): return lambda: x + 1
... 
>>> t = make_thunk(1)
>>> t()
2

Al usar esta técnica, se puede implementar una evaluación perezosa en un lenguaje impaciente.

Por lo tanto, esperaba que Haskell no tuviera expresiones lambda sin parámetros porque el lenguaje ya es perezoso y no es necesario crear expresiones retrasadas. Para mi sorpresa, descubrí que en Haskell es posible escribir la expresión lambda

\() -> "s"

que solo se puede aplicar al valor () así:

(\() -> "s") ()

dando el resultado

"s"

La aplicación de esta función a cualquier argumento que no sea () lanza una excepción (al menos por lo que pude ver durante mis pruebas). Esto parece diferente de la evaluación retrasada en Scheme y Python, porque la expresión todavía necesita un argumento para ser evaluado. Entonces, ¿qué significa una expresión lambda sin variables (como \() -> "s" ) en Haskell y para qué puede ser útil?

Además, me gustaría saber si existen expresiones lambda sin parámetros similares en (alguna variedad de) lambda-cálculo.

    
pregunta Giorgio 23.09.2014 - 23:07

3 respuestas

11

Bueno, las otras respuestas cubren lo que \() -> "something" significa en Haskell: una función única que toma () como argumento.

  • ¿Qué es una función sin argumentos? - Un valor. En realidad, en ocasiones puede ser útil pensar en las variables como funciones nulas que evalúan su valor. El let -syntax para una función sin argumentos (que en realidad no existe) termina dándole un enlace variable: let x = 42 in ...

  • ¿El cálculo lambda tiene funciones nulos? - No. Cada función toma exactamente un argumento. Sin embargo, este argumento puede ser una lista, o la función puede devolver otra función que tome el siguiente argumento. Haskell prefiere la última solución, por lo que a b c es en realidad dos llamadas a función ((a b) c) . Para simular funciones nullary, debe pasar algún valor de marcador de posición no utilizado.

respondido por el amon 23.09.2014 - 23:30
8

Estás malinterpretando lo que significa () en Haskell. No es la falta de un valor, es más bien el valor only del tipo Unit (el mismo tipo al que hace referencia un conjunto de paréntesis vacío () ).

Dado que las lambdas se pueden construir para usar la coincidencia de patrones, la expresión lambda \() -> "s" dice explícitamente "crear una función anónima, esperando una entrada que coincida con el patrón () ". No tiene mucho sentido hacerlo, pero ciertamente está permitido.

También puede utilizar la coincidencia de patrones con lambdas de otras maneras, por ejemplo:

map (\(a, b) -> a + b) [(1,2), (3,4), (5,6)] -- uses pattern matching to destructured tuples

map (\(Name first _) -> first) [Name "John" "Smith", Name "Jane" "Doe"] -- matches a "Name" data type and its first field

map (\(x:_) -> x) [[1,2,3], [4,5,6]] -- matches the head of a list
    
respondido por el KChaloux 23.09.2014 - 23:14
1

() -> "s" es una función lambda que toma un argumento:

ghci> :t (\() -> "s")
(\() -> "s") :: () -> [Char]

() , la tupla vacía (a veces conocida como Unidad), es un tipo completo en Haskell. Solo tiene un miembro (ignorando _|_ *), que también se escribe como () . Mira la definición de () :

data () = ()

Esto significa que el formulario en el lado izquierdo de su expresión lambda es sintácticamente una coincidencia de patrón que coincide con () , el único miembro del tipo () . Solo hay una forma válida de llamarlo (que es proporcionar () como argumento) porque solo hay un miembro válido del tipo () .

Tal función no es muy útil en Haskell, porque los términos predeterminados se evalúan perezosamente de todos modos, como observaste en tu pregunta.

Para obtener una explicación mucho más detallada, consulte esta respuesta .

* _|_ se llama "bottom" o "undefined". Siempre escribe chequeos, pero bloquea tu programa. El ejemplo clásico de cómo obtener un _|_ es let x = x in x .

    
respondido por el Benjamin Hodgson 23.09.2014 - 23:14

Lea otras preguntas en las etiquetas

Comentarios Recientes

y / o soluciones de meta programación basadas en cadenas en Haskell. La evaluación de la expresión es ciertamente útil para lenguajes como SPARK, pero creo que hay espacio para una mejor generación de código C. Nuevas características y aspectos destacados del código fuente: la fuente del código fuente Cabal para Lambda Expressions, un conjunto de pruebas basado en pruebas de Haskell programa realizado por John Aglianese. Evaluación de expresión macro para cálculos de tipo sintáctico. Declaraciones de conmutador... Lee mas