Translate

miércoles, 15 de abril de 2020

Introducción a las expresiones y ecuaciones en Haskell

¡Haskell no tiene declaraciones, solo expresiones!

En un lenguaje imperativo como C o Java, hay expresiones que denotan cálculos a pequeña escala (2 * x), y declaraciones que manejan secuenciación, bucles, condicionales y toda la operación a gran escala del programa.

Los lenguajes de programación funcionales puros no tienen ningún enunciado: no hay asignaciones ni saltos. En cambio, todo el cálculo se realiza evaluando expresiones

Una expresión se evalúa como un resultado (generalmente escrito e⇝r pero usaremos e -> r). Haskell usa una notación similar para números y operadores como la mayoría de los lenguajes :

    2 -> 2
    3 + 4 -> 7
    3 + 4 * 5 {equivalente a 3+ (4 * 5)} -> 23
    (3 + 4) * 5 {equivalente a 7 * 5} -> 35

Los paréntesis se usan para agrupar, al igual que en matemáticas.

Los operadores tienen prioridad, p. ∗ tiene una precedencia "más estricta" que +, entonces 2 + 3 ∗ 4 significa 2 + (3 ∗ 4).

Las expresiones pueden contener llamadas a funciones.

Una función toma argumentos, realiza algunos cálculos y produce resultados.

La función abs da el valor absoluto de un número. Para usar una función, se aplica a un argumento. Escribe la función seguida del argumento, separada por un espacio.

  abs 5 -> 5
  abs (-6) -> 6

Los paréntesis son para agrupar

  2 + 3 * 5
  2+ (3 * 5): puede ser más claro para algunos lectores
  abs 7

Por ejemplo, min y max son funciones que toman dos argumentos. Los argumentos se dan después de la función, separados por espacios en blanco.

Escriba min 3 8, no escriba min (3, 8);

    min 3 8 -> 3
    max 3 8 -> 8

La aplicación de funciones se une más fuerte que cualquier otra cosa. Entonces f x + 3 significa (f x) + 3 y no f (x + 3). Si un argumento para una función es una expresión, se deberá poner entre paréntesis.

Las ecuaciones se usan para dar nombres a los valores. Por ejemplo:

respuesta = 42

Una ecuación en Haskell es una ecuación matemática: dice que el lado izquierdo y el lado derecho denotan el mismo valor. El lado izquierdo debe ser un nombre al que le estás dando un valor.

Correcto: x = 5 * y
Incorrecto: 2 * x = (3 * x) ** 2 - La reasignación no está permitida en un FPL puro

A un nombre solo se le puede dar un valor. Los nombres a menudo se denominan "variables", pero no varían.

En Haskell las variables son constantes!

    n = 1 - ¡bien!
    x = 3 * n - bien
    n = x - Incorrecto: solo puede tener una definición de n

Una vez que le da un valor a un nombre, ¡nunca podrá cambiarlo!

Esto es parte del significado de "puro" y "sin efectos secundarios"

¿Qué pasa con n = n + 1?

En idiomas imperativos, decimos con frecuencia n: = n + 1 ¡Esta es una tarea, no una ecuación! Significa (1) calcular el lado derecho, utilizando el antiguo valor de n; luego (2) descarte el antiguo valor de n y sobrescríbalo con el nuevo valor. No hay ecuaciones en lenguajes imperativos como C y Java.

En Haskell, es válido escribir n = n + 1. ¡Esta es una ecuación, no una tarea! Significa: calcular el valor de n que tiene la propiedad de que n = n + 1. Haskell lo intentará y fallará.

¿Cómo puedes calcular sin asignaciones?

Piense en una declaración de asignación como hacer tres cosas:
Evalúa el lado derecho: calcular un valor útil.
Descarta el valor de la variable en el lado izquierdo: destruye un valor que podría o no ser útil.
Guarda el valor útil del RHS en la variable.

En un lenguaje funcional puro Nunca destruimos viejos valores. Simplemente calculamos nuevos útiles.

Si el valor anterior era realmente inútil, el recolector de basura recuperará su almacenamiento.