juan_gandhi: (Default)
Juan-Carlos Gandhi ([personal profile] juan_gandhi) wrote2010-01-29 08:30 pm

how to say in Haskell...


pairwise :: [a] →  [(a, a)]
pairwise [] = []
pairwise (x:y:rest) = (x,y) : pairwise rest

is there something that does it already? Could not figure out.

[identity profile] huzhepidarasa.livejournal.com 2010-01-30 10:03 am (UTC)(link)
нет, что-то не то — pairwise [1..] прекрасно работает, никакого переполнения стека не происходит.

[identity profile] faceted-jacinth.livejournal.com 2010-01-30 10:47 am (UTC)(link)
Это потому что она ещё и ленивая. pairwise 1:2:3 = (1, 2) : (pairwise [3]), на стеке ничего нет.

Точно так же foldr может спокойно сворачивать бесконечные списки ничего не переполняя.

[identity profile] huzhepidarasa.livejournal.com 2010-01-30 12:38 pm (UTC)(link)
не совсем так

*Main> foldr (+) 0 [1..]
*** Exception: stack overflow
*Main> sum [1..]
(комп намертво зависает, считая расходящуюся сумму, но переполнения не происходит)


foldr может сворачивать бесконечные списки только при наличии определенных оптимизаций, а в интерактивном режиме они отключены. sum же скомпилирована уже с оптимизациями и поэтому ничего не переполняет.

[identity profile] faceted-jacinth.livejournal.com 2010-01-30 12:55 pm (UTC)(link)
Да нет же. Это у вас (+) стековерфловится, а не фолдр. length (foldr (:) [] (take 10000000 [1..])) замечательно считается и в интерактивном режиме тоже, например.

Посмотрите на определение foldr, нет там никакой рекурсии. А (+) точно так же и foldl оверфловнет -- потому что он на самом деле ничего не вычисляет, а строит огромное дерево термов, при попытке которого и случается SO.

[identity profile] faceted-jacinth.livejournal.com 2010-01-30 12:56 pm (UTC)(link)
* при попытке вычислить значение которого

[identity profile] huzhepidarasa.livejournal.com 2010-01-30 01:37 pm (UTC)(link)
а, ну да, в общем понятно. только где такое определение foldr, чтобы без рекурсии?

[identity profile] faceted-jacinth.livejournal.com 2010-01-30 01:44 pm (UTC)(link)
Ну, я имею в виду, что сам фолдр не вычисляется рекурсивно -- не использует стек. Стек может использовать то, что его вызывает, или переданная ему функция, а сам фолдр (так же, как и pairwise) лениво и нерекурсивно идёт по списку слева-направо, не тратя никакой дополнительной памяти.

foldr f x0 x:xs = f x (foldr f x0 xs)
foldr f x0 [] = x0

[identity profile] huzhepidarasa.livejournal.com 2010-01-30 04:27 pm (UTC)(link)
ну, если считать, что рекурсивно — это со стеком, то да