【问题标题】:Composing Haskell filters编写 Haskell 过滤器
【发布时间】:2012-12-31 16:30:20
【问题描述】:

我正在将 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。

【问题讨论】:

  • 为什么现在一切都需要成为应用函子?好老的foldl (.) id怎么了?
  • 如何使用它来解决我的问题,尤其是带有索引部分的zip?
  • 这个链接 [String]-&gt;[String] 函数,而不是 String-&gt;Bool。顺便说一句,ap 在这里不好,xs ap ys 将每个 x 应用于每个 y。

标签: haskell composition applicative


【解决方案1】:

您可以使用 Data.Monoid 中的 Endo 包装器来获取一个可让您像这样使用 mconcat 的 monoid 实例:

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

【讨论】:

  • 我去看看。谢谢。
【解决方案2】:

换句话说,你想要:

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

但您也应该知道,filters 的管道很可能会被 GHC(据我所知)优化。所以创建这个函数可能不值得。请注意,您的 filterShort 会出现一些问题,因为它不是纯过滤器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 2011-08-03
    相关资源
    最近更新 更多