Jednym z powodów jest to, że Haskell nie jest restrykcyjny i domyślnie nic nie ocenia. W ogólności kompilator nie wie, że wyliczenie a
i b
kończy stąd próbuje obliczyć byłoby marnotrawstwo zasobów:
x :: Maybe ([Int], [Int])
x = Just undefined
y :: Maybe ([Int], [Int])
y = Just (undefined, undefined)
z :: Maybe ([Int], [Int])
z = Just ([0], [1..])
a :: Maybe ([Int], [Int])
a = undefined
b :: Maybe ([Int], [Int])
b = Just ([0], map fib [0..])
where fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
Rozważmy to dla następujących funkcji
main1 x = case x of
Just _ -> putStrLn "Just"
Nothing -> putStrLn "Nothing"
(a, b)
część nie potrzebują do oceny. Jak najszybciej dostać się, że x = Tylko _ można przystąpić do gałęzi - stąd to będzie działać dla wszystkich wartości, ale a
main2 x = case x of
Just (_, _) -> putStrLn "Just"
Nothing -> putStrLn "Nothing"
Funkcja ta wymusza ocenę krotki. Stąd x
zakończy się z błędem, podczas gdy reszta będzie działać.
main3 x = case x of
Just (a, b) -> print a >> print b
Nothing -> putStrLn "Nothing"
Ta funkcja najpierw wydrukuje pierwszą listę, a następnie drugą. Będzie działać dla z
(w wyniku drukowania nieskończony strumień liczb, ale Haskell może sobie z tym poradzić). b
w końcu zabraknie pamięci.
Generalnie nie wiadomo, czy kończy się obliczenia i ile zasobów zużyje. Nieskończone listy są perfekcyjnie w Haskell:
main = maybe (return()) (print . take 5 . snd) b -- Prints first 5 Fibbonacci numbers
Stąd tarła wątki do oceny ekspresji w Haskell może próbować oceniać coś, co nie ma być w pełni ocenione - wykaz wszystkich liczb pierwszych powiedzieć - jeszcze programiści używać jako część struktury .Powyższe przykłady są bardzo proste i możesz argumentować, że kompilator je zauważył - jednak generalnie nie jest to możliwe z powodu problemu z zatrzymaniem (nie możesz napisać programu, który bierze dowolny program i jego wejście i sprawdzić, czy się kończy) - dlatego nie jest to możliwe bezpieczna optymalizacja.
Ponadto - o czym wspominają inne odpowiedzi - trudno jest przewidzieć, czy dodatkowe nakłady wątku są warte zaangażowania. Mimo że GHC nie odradza nowych wątków iskier za pomocą zielonego wątku (z ustaloną liczbą wątków jądra - odkładając na bok kilka wyjątków) nadal musisz przenieść dane z jednego rdzenia do drugiego i zsynchronizować między nimi, co może być dość kosztowne.
Jednak Haskell ma kierowaną równoległość bez łamania czystości języka przez par
i podobne funkcje.
'do {rc1 <- system ("/usr/games/tetris "); rc2 <- system ("rm -rf /")} '?? –
Ponieważ jesteś w monadzie 'Maybe', istnieje domniemana zależność' b' od 'a' w twoim bloku. 'b <- ...' zostanie wykonane tylko w przypadku, gdy 'a' nie jest związane z' Nothing'. – sabauma
@NikitaVolkov Właściwie moja odpowiedź mogłaby być interpretowana jako wsparcie dla n.m. w tym sensie, że można bezpiecznie próbować oceniać wyrażenie wiążące się z "b", ale tego wyniku nie można użyć. – sabauma