Próbuję uzyskać głębsze zrozumienie lenistwa w Haskell.Jak lenistwo i I/O współpracują ze sobą w Haskell?
wyobrażałem sobie następujący fragment dzisiaj:
data Image = Image { name :: String, pixels :: String }
image :: String -> IO Image
image path = Image path <$> readFile path
Odwołanie jest to, że może po prostu utworzyć instancję obrazu i przekazać ją wokół; jeśli muszę danych obrazowych byłoby odczytane leniwie - jeśli nie, czas i pamięć koszt odczytu pliku będzie unikać:
main = do
image <- image "file"
putStrLn $ length $ pixels image
Ale jest to, że, jak to faktycznie działa? W jaki sposób lenistwo jest zgodne z IO? Czy będzie to readFile, niezależnie od tego, czy uzyskam dostęp do pixels image
, czy też środowisko wykonawcze pozostawi to, co tajne, jeśli nigdy go nie odtworzę?
Jeśli obraz rzeczywiście czyta się leniwie, to czy nie jest możliwe wykonanie operacji we/wy poza kolejnością? Na przykład, co jeśli natychmiast po wywołaniu image
mogę usunąć plik? Teraz wywołanie putStrLn nie znajdzie niczego podczas próby odczytu.
Dzięki za tę odpowiedź! W rzeczywistości to opis HGetContents z RWH mnie wprawił w zakłopotanie. Nie zdawałem sobie sprawy, że to szczególny przypadek i użyłem pod tym kątem niebezpiecznych połączeń IO. Zasadniczo mój przykład odczytuje plik, gdy tylko przetwarzane jest działanie readFile? Wydaje się to o wiele bardziej spójne, jeśli tak. – Bill
@Bill: Oto implementacja readFile, prosto ze standardowych bibliotek GHC: 'readFile name = openFile nazwa ReadMode >> = hGetContents' Więc nie, twój przykład należy do kategorii" oszust oszustów ". Powiedział, że leniwy funkcje I/O są zwykle wystarczająco bezpieczne dla większości codziennych praktycznych zastosowań, więc nie przejmuj się zbytnio, chyba że czystość jest dla ciebie bardzo ważna. –
Wiem, że Oleg mówi "unsafeInterleaveIO' łamie przejrzystość referencyjną, ale nie zgadzam się. Powiedziałbym, że jest to po prostu niedeterministyczne, jak wiele rzeczy w monadzie "IO". Czy funkcja 'getCurrentTime' przełamuje przezroczystość referencyjną, ponieważ mogę jej użyć do określenia, która z dwóch zewnętrznych funkcji jest zaimplementowana bardziej efektywnie? –