Tenés razón!!!
Antes que nada, para quien lee sin contexto aclaro: esto es un problema que viene de representar enteros en un largo fijo (64 bits, por ejemplo). No es propio de Haskell ni de la programación funcional. Nosotros en clase implementamos `fac' de tipo `Int -> Int'. El tipo `Int' usa enteros de máquina. GHC nos provee del tipo `Integer' que tiene precisión arbitraria. Si usamos `Integer' no vamos a tener este `glitch'. La moraleja es que si van a trabajar con valores grandes, `Integer' es la forma adecuada.
Ahora sí, volviendo al problema: otra forma de decir lo mismo es que en general en la representación binaria, al multiplicar dos números, la cantidad de ceros a la derecha del resultado es la suma de la cantidad de ceros a la derecha de los factores. En el caso de `fac' además el resultado crece rápidamente, entonces muy pronto tenemos overflow (por eso los números "negativos"), pero después a esos resultados incorrectos los seguimos multiplicando por números pares, entonces internamente seguimos acumulando ceros, hasta que eventualmente llegamos a cero, para siempre :)
En mi sistema (x86_64), `fac 65' es el último valor no nulo. Da -9223372036854775808. Ejercicio de otro curso: Calcular la representación de ese número en complemento a 2. El resultado sería una sorpresa si no fuera porque ahora entendemos lo que pasó :)
Antes que nada, para quien lee sin contexto aclaro: esto es un problema que viene de representar enteros en un largo fijo (64 bits, por ejemplo). No es propio de Haskell ni de la programación funcional. Nosotros en clase implementamos `fac' de tipo `Int -> Int'. El tipo `Int' usa enteros de máquina. GHC nos provee del tipo `Integer' que tiene precisión arbitraria. Si usamos `Integer' no vamos a tener este `glitch'. La moraleja es que si van a trabajar con valores grandes, `Integer' es la forma adecuada.
Ahora sí, volviendo al problema: otra forma de decir lo mismo es que en general en la representación binaria, al multiplicar dos números, la cantidad de ceros a la derecha del resultado es la suma de la cantidad de ceros a la derecha de los factores. En el caso de `fac' además el resultado crece rápidamente, entonces muy pronto tenemos overflow (por eso los números "negativos"), pero después a esos resultados incorrectos los seguimos multiplicando por números pares, entonces internamente seguimos acumulando ceros, hasta que eventualmente llegamos a cero, para siempre :)
En mi sistema (x86_64), `fac 65' es el último valor no nulo. Da -9223372036854775808. Ejercicio de otro curso: Calcular la representación de ese número en complemento a 2. El resultado sería una sorpresa si no fuera porque ahora entendemos lo que pasó :)