Распространенным заблуждением является то, что когда вы пишете x = ...
, вы присваиваете значение в Haskell.В Haskell каждый не присваивает значение, один объявляет один.
Таким образом, это означает, что в основном вы создали переменную x
в предложении where
, которое не x
в заголовке функции, поэтому что-то вроде:
fix :: Eq a => (a -> a) -> a -> a
fix f _ | f x == x = x
| otherwise = fix f x
where x = f x
Здесь вы таким образом определили x
в терминах самого себя: x = f x
, так чтоозначает, что если Haskell попытается оценить это, он начнет вычислять f(f(f(f(f(f(...))))))
, но без каких-либо проверок, если достигнута фиксированная точка .
Таким образом, решение состоит в том, чтобы ввести новую переменную,например x2
, и, таким образом, используйте это как:
fix :: Eq a => (a -> a) -> a -> a
fix f x | x == <b>x2</b> = x
| otherwise = fix f <b>x2</b>
where <b>x2</b> = f x
Так что здесь x2
является следующим x
.Учитывая x == x2
, мы возвращаем x
(или x2
), если нет, мы вычисляем фиксированную точку f
и x2
, поэтому мы продвинулись на один шаг в квесте " для фиксированной точки».