Wpadłem na problem nieskończonej pętli w Haskell i nie mogę zrozumieć, jaka jest przyczyna. Mam trzy wersje tego samego kodu poniżej. Pierwsza powoduje nieskończoną pętlę, podczas gdy dwie ostatnie nie. Jest to podstawowy wymyślony kod do generowania rekursywnie tablicy. W tym przypadku ma tylko trzy elementy, a jedyne wywołanie rekursywne dotyczy trzeciego elementu, który wybiera większą z dwóch pierwszych. Wydaje się, że instrukcja if a > b
powoduje pętlę (ale później pokazuję, że nie może być przyczyną).Dziwny <<loop>> wyjątek w generowaniu macierzy
import Data.Array
main :: IO()
main = print grid
where grid = array (0, 2) $ map func [0 .. 2]
func i
| i == 2 = let a = grid ! (i - 1)
b = grid ! (i - 2)
in if a > b
then (i, a)
else (i, b)
| otherwise = (i, 0)
W poniższej wersji, po prostu użyć max a b
zamiast rachunku if
. Tu nie ma pętli.
main :: IO()
main = print grid
where grid = array (0, 2) $ map func [0 .. 2]
func i
| i == 2 = let a = grid ! (i - 1)
b = grid ! (i - 2)
in (i, max a b)
| otherwise = (i, 0)
W poniższej wersji trzymam if
ale zip
indeksy zamiast wrócić krotki z func
. Ta również działa dobrze.
main :: IO()
main = print grid
where grid = array (0, 2) $ zip [0 .. 2] $ map func [0 .. 2]
func i
| i == 2 = let a = grid ! (i - 1)
b = grid ! (i - 2)
in if a > b
then a
else b
| otherwise = 0
tych dwóch pozostałych przypadkach wydają się wskazywać, że nie ma problemu z rekurencyjnej definicji lub wykorzystanie rachunku if
.
Co to pozostawia jako przyczynę pętli?
Stwierdzenie tego pytania jest absolutnie doskonałe, nawiasem mówiąc: wystarczy kod do obserwacji problemu, a także kilka obserwacji, które na ich twarz są całkowicie sprzeczne. Plus jasny zarys tego, co twoim zdaniem może być problemem i dowody, które nie były. Po prostu wspaniała zagadka dookoła. –