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.
¿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
+1 ¡Vaya, he estado usando Haskell durante años y nunca he notado que esa definición no está permitida! – is7s
@leftaroundabout 'safeDivide x 0 = Nothing; safeDivide = Just.: (/) '¿mejor? :) –