juan_gandhi: (Default)
[personal profile] juan_gandhi

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

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

Date: 2010-01-30 06:25 am (UTC)
From: [identity profile] permea-kra.livejournal.com
No, there is no standard way to do such things, i.e. there is no famous functions in base libraries that does something alike. You can build your one primitives to work with lists, however. Parser combinators library like ReadP is a good start point.

Date: 2010-01-30 06:42 am (UTC)
From: [identity profile] rinver.livejournal.com
Наверное так. Но что если этой функции подать список из нечётного количества элементов ? :) Или нефиг ? :)

Date: 2010-01-30 12:19 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Надо было добавить что-нибудь, вроде
pairwise (x:[]) = [(x,x)] или []
Без подобного паттерн получается неполным.

Date: 2010-01-30 07:23 am (UTC)
From: [identity profile] http://users.livejournal.com/_navi_/
Nothing standard comes to my. There's a problem with your code btw: pairwise is not tail-recursive and will blow up the stack.

Date: 2010-01-30 09:58 am (UTC)
From: [identity profile] huzhepidarasa.livejournal.com
а как сделать tail-recursive чтобы не разворачивало список?

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

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

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

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

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


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

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

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

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

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

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

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

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

Date: 2010-01-30 03:37 pm (UTC)
From: [identity profile] alexey-rom.livejournal.com
It isn't tail-recursive, but it is bounded-recursive (all recursive calls are under data constructors), which is more relevant when returning lazy structures. See, e.g. http://debasishg.blogspot.com/2009/01/to-tail-recurse-or-not-part-2-follow-up.html

Date: 2010-01-30 12:20 pm (UTC)
From: [identity profile] nivanych.livejournal.com
> is there something that does it already

А какая разница, если это пишется за полминуты?

Date: 2010-01-30 02:06 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Вот так будет лучше (и паттерн полный) ->
pairwise (x:y:rest) = (x,y) : pairwise rest
pairwise _ = []

Date: 2010-01-30 02:46 pm (UTC)
From: [identity profile] vyahhi.livejournal.com
zip xs (tail xs)
и как-нибудь взять все элементы с позиций 0,2..

Date: 2010-01-30 02:53 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Так и быть ;-)

takeNth _ [] = []
takeNth n lst = (head lst) : takeNth (drop n lst)

pairwise lst = takeNth 1 $ zip lst (tail lst)

Date: 2010-01-30 02:54 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Описался. Конечно же,
pairwise lst = takeNth 2 $ zip lst (tail lst)

Date: 2010-01-30 03:34 pm (UTC)
From: [identity profile] vyahhi.livejournal.com
Да, даже длиннее получилось :(

Date: 2010-01-30 03:36 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Зато более универсально.
Это самое takeNth может ещё где-то потребоваться.

Date: 2010-01-30 06:27 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Там вон снизу прикольную идею с cycle высказали.
На той же идее
takeNth n lst = map fst $ filter (\(x,t)-> t == 1) $ zip lst $ cycle [1..n]
Но по-моему, это уже извраты,
которые непонятно, для чего нужны,
кроме как, сэкономить лишнюю строчку.
Лучше писать тупо и понятно,
потом свой же код проще смотреть.

полет фантазии

Date: 2010-01-30 04:15 pm (UTC)
From: [identity profile] huzhepidarasa.livejournal.com
pairwise xs = uncurry zip $ pairmap (map snd) $ partition fst $ zip (cycle [True, False]) xs
  where pairmap f (x,y) = (f x, f y)

хотел без рекурсии и не определяя никаких вспомогательных ф-й, но не вышло

Re: полет фантазии

Date: 2010-01-30 04:21 pm (UTC)
From: [identity profile] huzhepidarasa.livejournal.com
объединяя с предыдущей идеей

pairwise xs = map snd $ filter fst $ zip (cycle [True, False]) $ zip xs (tail xs)

Re: полет фантазии

Date: 2010-01-30 06:06 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
О! cycle приходит на помощь!

Re: полет фантазии

Date: 2010-01-30 06:17 pm (UTC)
From: [identity profile] nivanych.livejournal.com
Прикольная идея ;-)

Date: 2010-01-31 10:33 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Как всегда, забыли unfoldr :)


splitInto n = unfoldr (chunk n)
where chunk _ [] = Nothing
chunk n lst = Just $ splitAt n lst

Date: 2010-02-01 12:12 am (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
Вот! Не слыхал про unfold раньше, но это то, что должно было вертеться на языке.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

September 2025

S M T W T F S
 1 2345 6
78 9 10 111213
14 151617 181920
212223 24252627
282930    

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 29th, 2025 11:20 am
Powered by Dreamwidth Studios