Общий и относительно простой способ перевести императивный код - заменить каждый базовый блок функцией и дать ему параметр для каждого элемента состояния, который он использует. Если это цикл, он будет повторно вызывать себя с разными значениями этих параметров. Если вы не заботитесь о печати промежуточных результатов, это означает:
Основная программа печатает результат внешнего цикла, который начинается с i
= 1 и counter
= 0.
main = print (outer 1 0)
where
Это константы, поэтому мы можем просто связать их вне циклов:
n = 46656
tr = floor (sqrt n)
Хвост цикла outer
вызывает себя с увеличением i
, и счетчик обновляется циклом inner
до i > tr
, затем возвращает окончательный счетчик.
outer i counter
| i <= tr = outer (i + 1) (inner 1 counter)
| otherwise = counter
where
Цикл inner
вызывает себя с увеличением j
, и его counter
(counter'
) увеличивается при i^2 * j^3 == n
, до j > tr
, затем он возвращает обновленный счетчик обратно в outer
, Обратите внимание, что это внутри предложения where
в outer
, потому что оно использует i
для вычисления res
- вы можете альтернативно сделать i
дополнительным параметром.
inner j counter'
| j <= tr = inner (j + 1) $ let
res = i ^ 2 * j ^ 3
in if res == n then counter' + 1 else counter'
| otherwise = counter'