【发布时间】:2014-01-16 12:07:40
【问题描述】:
我正在关注Gentle introduction to Haskell 教程,那里提供的代码似乎已损坏。我需要了解是不是这样,还是我对这个概念的理解是错误的。
我正在为自定义类型实现解析器:
data Tree a = Leaf a | Branch (Tree a) (Tree a)
打印功能方便
showsTree :: Show a => Tree a -> String -> String
showsTree (Leaf x) = shows x
showsTree (Branch l r) = ('<':) . showsTree l . ('|':) . showsTree r . ('>':)
instance Show a => Show (Tree a) where
showsPrec _ x = showsTree x
这个解析器很好,但是当有个空格时会中断
readsTree :: (Read a) => String -> [(Tree a, String)]
readsTree ('<':s) = [(Branch l r, u) | (l, '|':t) <- readsTree s,
(r, '>':u) <- readsTree t ]
readsTree s = [(Leaf x, t) | (x,t) <- reads s]
这个据说是更好的解决方案,但它不起作用没有空格
readsTree_lex :: (Read a) => String -> [(Tree a, String)]
readsTree_lex s = [(Branch l r, x) | ("<", t) <- lex s,
(l, u) <- readsTree_lex t,
("|", v) <- lex u,
(r, w) <- readsTree_lex v,
(">", x) <- lex w ]
++
[(Leaf x, t) | (x, t) <- reads s ]
接下来我选择一个解析器与read一起使用
instance Read a => Read (Tree a) where
readsPrec _ s = readsTree s
然后我使用 Leksah 调试模式在 ghci 中加载它(我猜这无关紧要),并尝试解析两个字符串:
read "<1|<2|3>>" :: Tree Int -- succeeds with readsTree
read "<1| <2|3> >" :: Tree Int -- succeeds with readsTree_lex
当lex 遇到前一个字符串的|<2... 部分时,它会拆分为("|<", _)。这与解析器的("|", v) <- lex u 部分不匹配,无法完成解析。
出现了两个问题:
- 如何定义真正忽略空格而不是需要空格的解析器?
- 如何定义使用 lex 拆分遇到的文字的规则
说到第二个问题——更多的好奇是因为定义我自己的词法分析器似乎比定义现有的规则更正确。
【问题讨论】: