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

问题描述

除非我缺少任何东西,否则似乎只有两种方法可以“遍历” Pandoc数据结构:

  1. BlockInline构造函数上手动进行模式匹配
  2. 通过Walkable type-class和相关的实用程序功能

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

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

解决方法

另一个答案指出了有用的query函数。我还要补充说,有一个package of pandoc lenses。您还问过宽度优先遍历,所以这两者都是。

import Data.Semigroup (First (..))

dfsFirstLink :: Walkable Inline b => b -> Maybe Text
dfsFirstLink = fmap getFirst . query (preview $ _Link . _2 . _1 . to First) 

bfsFirstLink :: Walkable Inline b => b -> Maybe Text
bfsFirstLink = fmap getFirst . getConst . traverseOf (levels query . folded) (Const . preview (_Link . _2 . _1 . to First))

-- Construct a walkable value where dfs != bfs
p :: Pandoc
p = Pandoc mempty [Plain [Note [Plain [Link mempty [] ("a","b")]]],Plain [Link mempty [] ("c","d")]]

>> dfsFirstLink p
Just "a"
>> bfsFirstLink p
Just "c"

不幸的是,一些临时实验表明它可能不像人们希望的那样懒惰。

,

Walkable类型类包含一个名为query的函数,具有以下类型签名:

query :: Monoid c => (a -> c) -> b -> c

Data.Semigroup中,有一个名为First的类型,具有一个半组实例,在该实例中,累加行为将返回“最左值”。

这可以与Monoid上的Maybe组合,从而将任何Semigroup转换为Monoidmempty的{​​{1}},给出您想要的行为。

例如,可以将功能从Nothing改成Inline -> Maybe String,就像这样:

Pandoc -> Maybe String

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

正如评论中指出的那样,也可以通过将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 专用于列表Monoid来编写此代码:

query

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...