编写Haskell过滤器

时间:2012-12-31 16:30:20

标签: haskell composition applicative

我正在将zxcvbn password strength算法转换为Haskell。

我有两个函数可以检查所有字符是否为ASCII并且可以进行强力攻击:

filterAscii :: [String] -- ^terms to filter
            -> [String] -- ^filtered terms
filterAscii = filter $ all (\ chr -> ord chr < 128)

filterShort :: [String] -- ^terms to filter
            -> [String] -- ^filtered terms
filterShort terms = map fst $ filter long $ zip terms [1..]
  where long (term, index) = (26 ^ length term) > index

我将这些内容组合成一个函数:

filtered :: [String] -- ^terms to filter
         -> [String] -- ^filtered terms
filtered = filterAscii . filterShort

我现在需要使用第三个过滤器来组合这些过滤器来检查这些术语是否为空:

filter (not . null) terms

我想到我正在创建一个过滤器链,并且创建一个单独的函数更有意义,该函数接受过滤函数列表并按给定的顺序组成它们。

如果我从阅读中回忆起来,我认为这是一个应用程序的工作。我可以使用申请表吗?

我不知道如何处理filterShort函数,我需要在过滤之前zip每个项目及其基于一的索引。

2 个答案:

答案 0 :(得分:3)

您可以使用Endo中的Data.Monoid包装来获取一个允许您使用mconcat的monoid实例:

Prelude> :m + Data.Monoid
Prelude Data.Monoid> :t appEndo $ mconcat [Endo filterAscii, Endo filterShort]
appEndo $ mconcat [Endo filterAscii, Endo filterShort] :: [String] -> [String]

答案 1 :(得分:2)

换句话说,你想要:

filters :: [a -> Bool] -> [a] -> [a]
filters fs = filter (\a -> and $ map ($ a) fs)

但你也应该知道GHC(据我所知)很可能会优化filter s的流水线。因此创建此功能可能不值得。请注意,filterShort会出现一些问题,因为它不是纯粹的过滤器。