2013-03-03 7 views
13

Jaka jest różnica między czystym a nieczystym w haskell? Czy podczas wykonywania IO w haskell należy zachować oddzielne czyste i nieczyste przedmioty?Jaka jest różnica między czystym a nieczystym w haskell?

+10

To podstęp! Wszystko w Haskell jest czyste - musisz wyjść poza Haskella (jak do systemu uruchomieniowego), aby uzyskać coś nieczystego. (... ale nie jest to przydatna odpowiedź aż do bardzo późnego doświadczenia Haskell.) –

Odpowiedz

20

Zasadniczo chcesz zachować jako mało kodu, jak to możliwe w sekcji „nieczystej”. Kod napisany w monadzie IO jest zawsze skażony brakiem bezpieczeństwa. Funkcja z podpisem IO Int zwróci liczbę całkowitą w monadzie IO, ale może na nią nadejść pocisk nuklearny na księżyc. Nie mamy możliwości poznania bez przestudiowania każdej linii kodu.

Na przykład, powiedzmy, że chcesz napisać program, który pobiera ciąg znaków i dołącza do niego ", stary".

main = do 
    line <- getLine 
    putStrLn $ line ++ ", dude" 

Niektóre części kodu muszą być w monady IO, ponieważ mają skutki uboczne. Obejmuje to getLine i putStrLn. Jednak połączenie dwóch strun nie jest możliwe.

main = do 
    line <- getLine 
    putStrLn $ addDude line 

addDude input = input ++ ", dude" 

Podpis addDude pokazuje, że jest czysty: String -> String. No IO tutaj. Oznacza to, że możemy założyć, że addDude zachowa się przynajmniej w ten sposób. Zajmie jeden ciąg i zwróci jeden ciąg. Niemożliwe jest, aby miał efekty uboczne. Nie można wysadzić księżyca.

+2

Dobra odpowiedź. Przepraszamy za możliwość naprawienia literówki w kodzie. Sugerowałbym również, że podpis 'addDude' byłby lepszy w pokazywaniu czystości, gdyby był obecny w kodzie. Jednym z powodów pisania podpisów typu jawnego jest właśnie udokumentowanie i weryfikacja, co złego na pewno się nie wydarzy. – pigworker

+0

+1 Fajna odpowiedź, koleś! – Landei

+0

@pigworker, dzięki! Wiesz, myślałem o umieszczeniu go tam, nie byłem pewien, czy to by miało znaczenie, więc poszłam na wzajemność. –

5

Czystość oznacza po prostu, powodując żadnych skutków ubocznych (odczyt z dysku, ruchomym ramieniem robota, etc.)

Oddzielenie funkcji czysta od nieczystych oznacza, że ​​można dowiedzieć się więcej o tym, co Twój kod ma zamiar zrobić. Na przykład, gdy powiesz 1 + 2, wiesz na pewno, że jego typ (Int -> Int -> Int) sprawia, że ​​jedyne co robi, to wziąć dwie liczby i wytworzyć trzecią liczbę. Jeśli jego typ to Int -> Int -> IO Int, może przesuwać ramię robota za każdym razem, gdy doda dwie liczby.

to dobry punkt wyjścia do podstawy Haskell można znaleźć tutaj: http://learnyouahaskell.com/introduction#so-whats-haskell

2

Wszystko w Haskell jest czyste. To, o czym czytasz, prawdopodobnie dotyczy kodu wewnątrz IO mondad kontra na zewnątrz. Po dodaniu czegoś do monopolu IO, nigdy nie może "uciec" - musisz pozostać w monadzie IO. Dlatego też monada IO ma tendencję do "atakowania" twojego kodu - jeśli masz rzecz, która zwraca IO, to każdy kod, który wywołuje, również musi zwrócić IO, i tak dalej. Dlatego najlepiej jest używać monopolu IO tylko tam, gdzie jest to konieczne, na najwyższym poziomie programu, jak to możliwe, i oddzielać wszelkie części obliczeń, które są czyste w czyste funkcje.

Powiązane problemy