如何解决在大型Pandoc中有效地搜索单个元素
除非我缺少任何东西,否则似乎只有两种方法可以“遍历” Pandoc
数据结构:
- 在
Block
和Inline
构造函数上手动进行模式匹配 - 通过
Walkable
type-class和相关的实用程序功能
使用Walkable
类型类,有没有一种有效的方法来搜索 first 匹配元素(最好以广度优先),并在遍历后立即停止遍历找到了吗?在我看来,Walkable
类型类周围的所有函数无论如何都将遍历整个数据结构。
如果没有,我想唯一的方法是对Block
和Inline
构造函数进行模式匹配,然后自行构建。
解决方法
另一个答案指出了有用的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
转换为Monoid
为mempty
的{{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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。