Рассмотрим haskell-выражение, подобное следующему: (Простой пример, не говорите мне, каков очевидный способ! ;)
toBits :: Integral a => a -> [Bool]
toBits 0 = []
toBits n = x : toBits m where
(m,y) = n `divMod` 2
x = y /= 0
Поскольку эта функция не является хвостовой рекурсией, можно также написать:
toBits :: Integral a => a -> [Bool]
toBits = toBits' [] where
toBits' l 0 = l
toBits' l n = toBits (x : l) m where
(m,y) = n `divMod` 2
x = y /= 0
(Надеюсь, в этом выражении нет ничего плохого)
Я хочу спросить, какое из этих решений лучше. Преимущество первого заключается в том, что его можно очень легко вычислить частично (потому что Haskell останавливается на первом :
не нужно), а второе решение (очевидно) является хвостовой рекурсией, но, на мой взгляд, оно должно быть полностью оценивается, пока вы не можете получить что-то.
Фоном для этого является мой парсер Brainfuck (см. мой вопрос по оптимизации), который реализован очень уродливо (различные reverse
инструкции... ох), но может быть легко реализован в первом - назовем его "полу-хвост-рекурсия" способ.
if y == 0 then False else True
можно записать проще какy /= 0
. - person kennytm   schedule 09.09.2010