Estoy tratando de obtener una comprensión más profunda de la pereza en Haskell.¿Cómo funcionan la pereza y la E/S juntas en Haskell?
me estaba imaginando el siguiente fragmento de hoy:
data Image = Image { name :: String, pixels :: String }
image :: String -> IO Image
image path = Image path <$> readFile path
El atractivo aquí es que yo podría simplemente crear una instancia de imagen y pasarlo alrededor; si necesito los datos de imagen que se leería con pereza - si no, el costo de tiempo y la memoria de la lectura del archivo se evitaría:
main = do
image <- image "file"
putStrLn $ length $ pixels image
Pero es que cómo funciona realmente? ¿Cómo es la pereza compatible con IO? ¿Se llamará readFile independientemente de si accedo a pixels image
o el tiempo de ejecución dejará ese thunk no evaluado si nunca me refiero a él?
Si la imagen es de hecho leída perezosamente, entonces ¿no es posible que las acciones de E/S puedan ocurrir desordenadas? Por ejemplo, ¿qué ocurre si, inmediatamente después de llamar al image
, borro el archivo? Ahora la llamada putStrLn no encontrará nada cuando intente leer.
Gracias por esta respuesta! De hecho, fue la descripción de hGetContents de RWH la que me confundió sobre este tema. No me di cuenta de que era un caso especial y usé llamadas IO inseguras debajo. Entonces, básicamente, ¿mi ejemplo lee el archivo tan pronto como se procesa la acción readFile? Eso parece mucho más consistente si es así. – Bill
@Bill: Aquí está la implementación de readFile, directamente de las librerías estándar de GHC: 'readFile name = openFile name ReadMode >> = hGetContents' Así que no, tu ejemplo cae dentro de la categoría" tramposo infiel ". Dicho esto, las funciones de E/S perezosas suelen ser lo suficientemente seguras para la mayoría del uso diario, así que no te preocupes demasiado a menos que la pureza sea muy importante para ti. –
Sé que Oleg dice 'unsafeInterleaveIO' rompe la transparencia referencial, pero no estoy de acuerdo. Yo diría que es meramente no determinista, como muchas cosas en la mónada de 'IO'. ¿'GetCurrentTime' rompe la transparencia referencial porque puedo usarla para determinar cuál de las dos funciones extrínsecamente iguales se implementa de manera más eficiente? –