我正在解决项目欧拉问题,该问题涉及具有特定属性的所有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
如果m有n个数字则返回true,我可以这样做:
nDigitNumsWithCoolProperty n = f (hasNDigits n) numsWithCoolProperty
nDigitNumsWithOtherCoolProperty n = f (hasNDigits n) numsWithOtherCoolProperty
无论如何,我的问题是关于函数f
,它与dropWhile和takeWhile具有相同的类型:它是否已经存在于某个地方?如果没有,那么它的名字会是什么?我能想到的只有dropUntilTakeWhile
,但我确信那里有一个更好的名字。
答案 0 :(得分:7)
你的职能:
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
函数组的一部分。它也与lexing有关,你可以在其中收集一些与谓词匹配的标记。
因此,您可以将此函数称为gather
或lex
或类似的东西。