Uso de rangos de Haskell: ¿Por qué mapear una función de punto flotante en un rango hace que devuelva un elemento adicional?

Sé que las carrozas pueden conducir a un comportamiento extraño en los rangos debido a su naturaleza imprecisa. Esperaría la posibilidad de valores imprecisos. Por ejemplo:[0.1,0.3..1] podría dar[0.1,0.3,0.5,0.7,0.8999999999999999] en lugar de[0.1,0.3,0.5,0.7,0.9]

Además de la pérdida de precisión, sin embargo, obtengo un elemento adicional:

ghci> [0.1,0.3..1]
[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]

Esto es raro, pero explicadoaquí. Podría solucionarlo así, supongo:

ghci> [0.1,0.3..0.99]
[0.1,0.3,0.5,0.7,0.8999999999999999]

Pero eso es un poco asqueroso. Tal vez hay una forma más limpia. Para este ejemplo simple, por supuesto, podría usar el rango[0.1,0.3..0.9] Y todo está bien.

Pero en un ejemplo más complejo, es posible que no sepa rápidamente (o me importe averiguar, si soy vago) el límite superior exacto que debo usar. Entonces, solo haré un rango de enteros y luego dividiré por 10, ¿verdad? No:

ghci> map (/10) [1,3..10]
[0.1,0.3,0.5,0.7,0.9,1.1]

Cualquier función de punto flotante parece causar este comportamiento:

ghci> map (*1.0) [1,3..10]
[1.0,3.0,5.0,7.0,9.0,11.0]

Mientras que una función no flotante no:

ghci> map (*1) [1,3..10]
[1,3,5,7,9]

Si bien parece poco probable, pensé que quizás estaba en juego una evaluación perezosa, e intenté forzar la evaluación del rango primero:

ghci> let list = [1,3..10] in seq list (map (*1.0) list)
[1.0,3.0,5.0,7.0,9.0,11.0]

Obviamente, usar la lista literal en lugar del rango funciona bien:

ghci> map (*1.0) [1,3,5,7,9]
[1.0,3.0,5.0,7.0,9.0]

ghci> let list = [1,3,5,7,9] in seq list (map (*1.0) list)
[1.0,3.0,5.0,7.0,9.0]

Tampoco es solo mapeo:

ghci> last [1,3..10]
9

ghci> 1.0 * (last [1,3..10])
11.0

¿Cómo puede afectar la aplicación de una función al resultado de un rango el resultado real evaluado de ese rango?

Respuestas a la pregunta(1)

Su respuesta a la pregunta