Существует ли эта «фильтрующая» функция?Какое было бы хорошее название для такой функции? - PullRequest
1 голос
/ 11 июня 2011

Я решаю задачу Project Euler, которая включает все n-значные числа с определенным свойством. Кажется, что самый простой способ получить их - это получить список всех чисел с этим свойством (которое будет бесконечно длинным), а затем выбрать те, которые имеют правильное количество цифр. Как это:

numsWithCoolProperty = filter hasCoolProperty [1..]

nDigitNumsWithCoolProperty n = takeWhile (< 10^n) $ dropWhile (<= 10^(n-1)) numsWithOtherCoolProperty

Но теперь, если я хочу сделать то же самое с другим свойством, я повторюсь:

nDigitNumsWithOtherCoolProperty n = takeWhile (< 10^n) $ dropWhile (<= 10^(n-1)) numsWithOtherCoolProperty

поэтому я хочу функцию, которая захватывает логику dropWhile / takeWhile. Что-то вроде:

f :: (a -> Bool) -> [a] -> [a]
f pred = takeWhile pred . dropWhile (not . pred)

и затем, если у меня есть предикат hasNDigits n m, который возвращает true, если m имеет n цифр, я могу сделать:

nDigitNumsWithCoolProperty n = f (hasNDigits n) numsWithCoolProperty
nDigitNumsWithOtherCoolProperty n = f (hasNDigits n) numsWithOtherCoolProperty

В любом случае, мой вопрос касается функции f, которая имеет тот же тип, что и dropWhile и takeWhile: она уже где-то существует? Если нет, то каково будет хорошее название для этого? Все, что я могу придумать, это что-то вроде dropUntilTakeWhile, но я уверен, что есть лучшее имя.

1 Ответ

7 голосов
/ 11 июня 2011

Ваша функция:

f pred = takeWhile pred . dropWhile (not . pred)

Сильно связана с функциями span и break, как вы можете видеть:

span  :: (a -> Bool) -> [a] -> ([a], [a]) 

break :: (a -> Bool) -> [a] -> ([a], [a])       

Давайте рассмотрим несколько примеров:

> span (< 3) [1,2,3,4,1,2,3,4]
([1,2],[3,4,1,2,3,4])

> break (< 3) [1,2,3,4,1,2,3,4]
([],[1,2,3,4,1,2,3,4])

и ваша функция:

> f (< 3) [1,2,3,4,1,2,3,4]
[1,2]

Теперь у нас есть один закон, относящийся span к takeWhile и dropWhile,

span p xs эквивалентно (takeWhile p xs, dropWhile p xs)

, поэтому мы можем рассмотреть вашу функцию как часть span и break группа функций.Это также относится к лексингу, где вы собираете некоторый токен, который соответствует предикату.

Итак, вы можете вызвать эту функцию gather или lex или что-то подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...