хвостато-рекурсивные функции в монадах
Jan. 24th, 2007 07:54 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Когда мы пишем монадическую функцию с хвостовой рекурсией, то явно эта функция не хвостато-рекурсивная:
Например, эта функция выглядит как
Я здесь хвостатости не вижу. Я предполагаю, что реализация
Чтобы было ясно, что я имею в виду:
Откуда следует, что
Кто подскажет?
loop = do
cmd <- getLine
if (cmd == ":q")
then return ()
else loop
Например, эта функция выглядит как
loop = getLine >>= \cmd ->
if (cmd == ":q")
then return ()
else loop
Я здесь хвостатости не вижу. Я предполагаю, что реализация
(>>=)
такова, что bind
переводит запись c foo = m >>= foo
в хвостовую рекурсию. Чтобы было ясно, что я имею в виду:
instance Monad Identity where
return a = Identity a
m >>= k = k (runIdentity m)
Откуда следует, что
f = m >>= f
преобразуется в f = f (runIndentity m)
. Но, с другой стороны, это только в случае инлайна будет возможна такая оптимизация. И фиг знает, что там с другими монадами. Полагаю, что их тоже можно развернуть в хвостатую запись. Может быть кто нибудь поможет с объяснением или ссылкой - почему так? Может быть на это влияет семантика монад, в частности то, что в m >>= f
f
не будет выполнено до тех пор, пока не будет выполнен m
.Кто подскажет?
no subject
Date: 2007-01-25 06:54 am (UTC)leak = do {a <- [1,2,3] ; leak }
Не проверял. Но думаю, 100% будет утечка.
no subject
Date: 2007-01-25 07:15 am (UTC)leak !! 1000 замерает. На Сtrl-C не реагирует.
А вот код leak arg = do { a <- [1,2,3]; leak a }
как раз ведет себя как и ожидалось:
stack overflow на leak 1 !! 1000
no subject
Date: 2007-01-25 10:57 am (UTC)Надо будет поглядеть насчёт списков внимательнее, а то я не пойму ни фига - с чего это leak без аргументов не течёт
no subject
Date: 2007-01-25 12:15 pm (UTC)Может deadlock какой случился с ghci? :)
no subject
Date: 2007-01-25 12:38 pm (UTC)это после инлайнинга. Это выражение тоже ничего не делает, когда запускаю leak !! 1000