2016-04-19 6 views
3

У меня есть список значений, которые я бы хотел взять, пока значение увеличивается. Я предполагаю, что он всегда будет возглавлять список, а затем сравнить его со следующим значением. Функция будет продолжаться до тех пор, пока она продолжает увеличиваться. По достижении элемента списка, который меньше или равен первому значению, возвращается список.Возьмите из списка при увеличении

takeIncreasing :: (Ord a) => [a] -> [a] 
takeIncreasing [1,2,3,4,3,5,6,7,8] -- Should return [1,2,3,4] 

Откидна мог сравнить last элемент накопления со следующим значением и добавить, если условие выполняется, но будет продолжаться до конца списка. Я хотел бы, чтобы функция прекратила принимать в первом случае ограничение не выполнялось.

Это похоже на приложение монады, но не может определить, выполняет ли существующая монада это.

ответ

8

Сложите [...] и продолжайте до конца списка. Я хотел бы, чтобы функция прекратила принимать в первом случае ограничение не выполнялось.

Права складка может вызвать короткое замыкание:

fun :: Ord a => [a] -> [a] 
fun []  = [] 
fun (x:xs) = x: foldr go (const []) xs x 
    where go x f i = if i < x then x: f x else [] 

тогда

\> fun [1,2,3,4,3,undefined] 
[1,2,3,4] 

или бесконечный список размера:

\> fun $ [1,2,3,4,3] ++ [1..] 
[1,2,3,4] 
+0

Nitpick: правая складка может короткое замыкание ** в лениво оцененном языке **, как Haskell. Но это, конечно, очень важный момент, чтобы знать! Многие люди, которые приезжают в Хаскелл, имеют опыт работы с нетерпением оцененными языками, где правильные складки часто избегают, потому что они (а) продолжаются до конца списка и (б) удаляют стек в длинных списках. Но «складка» Haskell может быть и часто используется способами, которые не имеют этой проблемы, и на самом деле, в Haskell 'foldl' - это тот, который чаще всего рискует выдувать стек! –

4

правых складок являются магическими, так что вы никогда даже нужно сопоставить шаблон в списке.

twi xs = foldr go (const []) xs Nothing where 
    go x _ (Just prev) 
    | x < prev = [] 
    go x r _ = x : r (Just x) 
2

раствор без складок:

takeIncreasing :: Ord a => [a] -> [a] 
takeIncreasing [] = [] 
takeIncreasing (x:xs) = (x :) . map snd . takeWhile (uncurry (<)) $ zip (x:xs) xs 
3

Или один, что ИМО имеет немного меньшую сложность кода:

takeIncreasing :: Ord x => [x] -> [x] 
takeIncreasing (x:x':xs) | x < x' = x : takeIncreasing (x':xs) 
         | otherwise = [x] 
takeIncreasing xs = xs 

Это одна лишь немного менее умным, чем предыдущие предложения. Мне нравится неразумный код.

Смежные вопросы