Haskel. Проблема с иммутабельностью в рекурсивной функции

Пишу небольшую консольную игрушку, есть карта вида:

#######
#%....#
#.....#
#######

А также функция вечно вызывающая саму себя, этакий mainloop. Каждый вызов функция запрашивает ввод символа - wasd например, и символ % должен перемещаться по карте в соответствующем направлении. Проблема же возникла с обновлением карты в бесконечной рекурсии, в императивных языках я бы просто всегда менял карту, а вот в haskell`e решение я придумать не могу. Заранее спасибо.


Ответы (1 шт):

Автор решения: Fyodor Soikin

Стандартный способ отслеживать состояние алгоритма от одной итерации к другой - это передавать его в качестве параметра:

mainloop currentMap = do
    playerCommand <- readLn
    let newMap = modifyMap currentMap playerCommand
    mainloop newMap

main = mainloop initialMap

Разумеется в Хаскелле также есть поддержка настоящих изменяемых ячеек памяти, которыми можно пользоваться точно так же, как изменяемыми переменными в других языках. Пожалуй самый простой вариант - это IORef:

mainloop mapRef = do
    currentMap <- readIORef mapRef
    playerCommand <- readLn
    let newMap = modifyMap currentMap playerCommand
    writeIORef newMap mapRef
    mainloop mapRef

main = mainloop =<< newIORef initialMap

Но, конечно же, в данном случае изменяемые ячейки - это из пушки по воробьям. Их вообще следует избегать по мере возможности, ибо изменяемая память - большой источник ошибок. Хаскель не зря весь неизменяемый, не просто так.

→ Ссылка