在大型 Pandoc 中高效搜索单个元素

Sau*_*nda 5 haskell pandoc

除非我遗漏了一些东西,否则似乎只有两种方法可以“遍历”Pandoc数据结构:

  1. 手动模式匹配BlockInline构造函数
  2. 通过Walkabletype-class和相关的效用函数

使用Walkable类型类,是否有一种有效的方法来搜索第一个匹配元素(最好以广度优先的方式),并在找到后立即停止遍历?在我看来,无论如何,围绕Walkable类型类的所有函数都将遍历整个数据结构。

如果没有,我想唯一的方法是对BlockInline构造函数进行模式匹配并自行构建。

Joe*_*Joe 2

类型类Walkable包含一个名为的函数query类包含一个使用以下类型签名

query :: Monoid c => (a -> c) -> b -> c
Run Code Online (Sandbox Code Playgroud)

Data.Semigroup,有一个名为 的类型First,带有一个半群实例,其中累积行为是返回“最左边的值”。

Monoid这可以与on结合使用Maybe,将 anySemigroup变成Monoid of memptyNothing以提供您想要的行为。

例如,将函数从Inline -> Maybe String, 调整为Pandoc -> Maybe String, 可以像这样完成:

import Text.Pandoc
import Text.Pandoc.Walk (query)
import Data.Semigroup

findUrl :: Inline -> Maybe String
findUrl (Link _ _ target) = Just $ fst target
findUrl _ = Nothing

findFirstUrl :: Pandoc -> Maybe String
findFirstUrl = (fmap getFirst) . (query findUrl')
  where
    findUrl' :: Inline -> Maybe (First String)
    findUrl' = (fmap First) . findUrl

Run Code Online (Sandbox Code Playgroud)

关于您担心这将遍历整个数据结构:Haskell 很懒;它不应超出其需要的范围。

正如评论中所指出的,也可以通过专门针对queryList Monoid 来编写此代码:

import Text.Pandoc
import Text.Pandoc.Walk (query)
import Data.Maybe (listToMaybe)

findUrl :: Inline -> [String]
findUrl (Link _ _ target) = [fst target]
findUrl _ = []

findFirstUrl :: Pandoc -> Maybe String
findFirstUrl = listToMaybe . (query findUrl)
Run Code Online (Sandbox Code Playgroud)