【发布时间】:2016-04-05 05:27:38
【问题描述】:
我正在使用simple pattern matching 和the Reader monad 遍历an AST。
在我的项目的其他地方,我定义了 a walk function 用于遍历 AST,它的核心使用 foldl 将访问树中每个节点的结果减少为单个幺半群结果(例如,to produce a "symbol table"来自树中的特殊节点)。
我的问题是:是否可以将这两种方法结合起来并使用像我的 walk 函数这样的函数:
walk :: Monoid a => (Node -> a) -> a -> Node -> a
walk f acc n = foldl (walk f) (acc <> f n) children
where
children = case n of
Blockquote b -> b
DocBlock d -> d
FunctionDeclaration {} -> functionBody n
List l -> l
ListItem i -> i
Paragraph p -> p
Unit u -> u
_ -> [] -- no Node children
和Reader——就像下面代码中的遍历(为简洁起见省略了一些位)——同时?
markdown :: Node -> String
markdown n = runReader (node n) state
where state = State (getSymbols n) (getPluginName n)
node :: Node -> Env
node n = case n of
Blockquote b -> blockquote b >>= appendNewline >>= appendNewline
DocBlock d -> nodes d
FunctionDeclaration {} -> nodes $ functionBody n
Paragraph p -> nodes p >>= appendNewline >>= appendNewline
Link l -> link l
List ls -> nodes ls >>= appendNewline
ListItem l -> fmap ("- " ++) (nodes l) >>= appendNewline
Unit u -> nodes u
我在这里使用的动机是我的walk 函数已经编码了如何获取每个模式的孩子以及如何执行 AST 的按序遍历的知识。我真的不想为每次遍历重新实现它,所以在更多地方使用walk 会很好,包括我需要使用Reader 的地方(可能稍后,State,可能在堆栈)。
这些东西可以有效地结合起来吗?
【问题讨论】:
-
我不知道,我现在也没有时间深入研究,但我猜你应该少看
foldl,多看traverse。
标签: haskell monads fold parsec reader-monad