хвостато-рекурсивные функции в монадах

Jan 24, 2007 19:54

Когда мы пишем монадическую функцию с хвостовой рекурсией, то явно эта функция не хвостато-рекурсивная:

loop = do
cmd <- getLine
if (cmd == ":q")
then return ()
else loop

чуть-чуть кода и много вопросов )

монады, haskell, программирование

Leave a comment

rvp74 January 24 2007, 16:59:20 UTC
Может стоит вопрос поставить иначе: возможен ли тут memory leak?

Reply

lomeo January 24 2007, 17:05:57 UTC
Без проблем, давай так вопрос поставим :-)
Возможен тут меморилик? Нет? Почему нет?

Reply

rvp74 January 24 2007, 17:16:12 UTC
считай что оператор (>>=) конструирует замыкание, которое когда будет запущенно сначала вызывает левую часть. Потом вызывает правую часть, которая просто возвратит новое замыкание. И дальше управление будет передано ему. Это и будет хвостовая рекурсия, поскольку возвращается тот же объект-замыкание

Reply

rvp74 January 24 2007, 17:26:32 UTC
Мой тебе совет. Возьми ocaml или lisp и реализуй свой монаду. Эти вопросы исчезнуть.
У меня монада была реализована как замыкание. Насколько я помню IO реализованна так же.

Reply

lomeo January 24 2007, 20:09:38 UTC
Спасибо, хороший совет, так и сделаю.

Reply

lomeo January 25 2007, 00:32:54 UTC
Переписал монады на схему, без подмешивание ленивости не получается сделать вечный цикл.
Хорошо, не поленился добавил лени :-) Работает, хвала всевышнему.

теперь получается что то вроде (словами Хаскеля)

loop = delay (\world ->
let (value, next_world) = (force (write 5)) world)
in (force loop) next_world

Ну, это больше похоже на хвостовую рекурсию. Особенно в Haskell это выльется loop world = let .. in loop next_world.
С IO разобрался, хорошо. Но неужели мне так со всеми монадами надо разбираться, чтобы понять? Должно же быть где то теоретическое обоснование! Какое то простое объяснение, следующее из закона монад или ещё что...

Reply

rvp74 January 25 2007, 06:54:37 UTC
Для для каждого вида монады надо отдельный подход. В случае List Monad будет все по другому:

leak = do {a <- [1,2,3] ; leak }

Не проверял. Но думаю, 100% будет утечка.

Reply

rvp74 January 25 2007, 07:15:28 UTC
хм, этот код странно себя ведет:
leak !! 1000 замерает. На Сtrl-C не реагирует.

А вот код leak arg = do { a <- [1,2,3]; leak a }
как раз ведет себя как и ожидалось:
stack overflow на leak 1 !! 1000

Reply

lomeo January 25 2007, 10:57:41 UTC
Понял, значит моё предположение о принадлежности этого свойства всем монадам неверно.

Надо будет поглядеть насчёт списков внимательнее, а то я не пойму ни фига - с чего это leak без аргументов не течёт

Reply

rvp74 January 25 2007, 12:15:00 UTC
Не течет потому что ghci на leak !! 1000 ничего не делает (загрузка ЦП 0%).
Может deadlock какой случился с ghci? :)

Reply

rvp74 January 25 2007, 12:38:56 UTC
leak = leak ++ (leak ++ leak)

это после инлайнинга. Это выражение тоже ничего не делает, когда запускаю leak !! 1000

Reply


Leave a comment

Up