2012-01-05 4 views
22

Noté hoy que tal definiciónDefinición de una función mediante ecuaciones con diferente número de argumentos

no es posible. Solo tengo curiosidad por saber cuál es la (buena) razón detrás de esto. Debe haber uno muy bueno (es Haskell después de todo :)).

Nota: No estoy buscando sugerencias para implementaciones alternativas al código anterior, es un ejemplo simple para demostrar mi punto.

+4

¿Lo llama "seguro"? Deje que devuelva un "Tal vez" o algo, o ejecute alguna excepción conocida, o úsela en un "tipo nuevo" que sea exclusivo para funciones no degeneradas que trate como miembros de, p. el espacio L² Hilbert (es decir, solo conjuntos definidos de módulo nulo); eso sería seguro. ¡Simplemente definir 'x/0 = x' _ad hoc_ para todas las instancias' Fractional' es horriblemente no canónico! - Bueno, probablemente solo fue un ejemplo. – leftaroundabout

+0

+1 ¡Vaya, he estado usando Haskell durante años y nunca he notado que esa definición no está permitida! – is7s

+0

@leftaroundabout 'safeDivide x 0 = Nothing; safeDivide = Just.: (/) '¿mejor? :) –

Respuesta

25

Creo que es principalmente por coherencia, por lo que todas las cláusulas se pueden leer de la misma manera, por así decirlo; es decir, cada RHS está en la misma posición en el tipo de la función. Creo que enmascararía bastantes errores tontos si permitieras esto también.

También hay una ligera peculiaridad semántica: digamos que el compilador completó estas cláusulas para tener el mismo número de patrones que las otras cláusulas; es decir, que su ejemplo se convertiría en

safeDivide x 0 = x 
safeDivide x y = (/) x y 

Consideremos ahora si la segunda línea en vez había sido safeDivide = undefined; en ausencia de la cláusula anterior, safeDivide sería , pero gracias a la expansión eta realizada aquí, es \x y -> if y == 0 then x else ⊥ - por lo que safeDivide = undefined en realidad no define safeDivide como ! Esto parece lo suficientemente confuso como para justificar la prohibición de tales cláusulas, IMO.

+0

Entonces, ¿no hay una razón técnica más profunda? – aelguindy

+1

@aelguindy: ¡En realidad, sí! He actualizado mi respuesta :) – ehird

+0

Gracias por el formato del código editar :), lo haremos a partir de ahora. Me tomó un tiempo entender por qué es const (const \ bot), pero ahora lo entiendo. – aelguindy

11

El significado de una función con múltiples cláusulas se define por el estándar Haskell (section 4.4.3.1) través de la traducción a un lambda y case declaración:

fn pat1a pat1b = r1 
fn pat2a pat2b = r2 

convierte

fn = \a b -> case (a,b) of 
    (pat1a, pat1b) -> r1 
    (pat2a, pat2b) -> r2 

Esto es para que la definición de función La forma de hacer las cosas es buena y consistente, y el significado de cada una no se especifica de forma redundante y confusa.

Esta traducción solo tiene sentido cuando cada cláusula tiene el mismo número de argumentos. Por supuesto, podría haber reglas adicionales para arreglar eso, pero complicarían la traducción con poca ganancia, ya que probablemente no quieras definir cosas así de todos modos, por el bien de tus lectores.

4

Haskell lo hace de esta manera porque sus predecesores (como LML y Miranda) lo hicieron. No hay razón técnica para que tenga que ser así; las ecuaciones con menos argumentos podrían ser eta expandidas. Pero tener una cantidad diferente de argumentos para diferentes ecuaciones es probablemente un error tipográfico en lugar de intencional, por lo que en este caso prohibimos algo sensible & raro para obtener un mejor informe de errores en el caso común.

Cuestiones relacionadas