我在Graham Hutton的Haskell编程的第8章中,我正在复制代码并在GHC中对其进行测试.
请参阅此处的幻灯片:http://www.cis.syr.edu/~sueo/cis352/chapter8.pdf,特别是幻灯片15
到目前为止我复制的相关代码是:
type Parser a = String -> [(a, String)]
pih_return :: a -> Parser a
pih_return v = \inp -> [(v, inp)]
failure :: Parser a
failure = \inp -> []
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x,xs)]
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
if p x then pih_return x else failure
Run Code Online (Sandbox Code Playgroud)
我已经return从书中更改了该函数的名称,pih_return以便它不会与Prelude return函数冲突.
错误在最后一个函数中sat.我直接从书中复制了这个.
正如你可能可以看到p是从功能Char到Bool(例如isDigit),并x为类型的[(Char, String)],所以这是第一个错误.
然后pih_return取一个值v,并返回[(v, inp)]其中inp一个String.这会导致错误,sat因为v传递的x不是a Char.
我已经提出了这个解决方案,通过明确包含inp到sat
sat :: (Char -> Bool) -> Parser Char
sat p inp = do x <- item inp
if p (fst x) then pih_return (fst x) inp else failure inp
Run Code Online (Sandbox Code Playgroud)
这是解决问题的最佳方法吗?
第一个sat不能工作,Parser必须是monad才能使用do符号.为了使它成为monad实例,newtype必须使用它.
我不拥有这本书,但我想作者想要从一个简单的解析器类型开始,然后将它扩展为一个完整的monad,我怀疑你已将非monadic版本的定义与Parsermonad 之一混淆了(sat并且错过了沿途的monad实例声明.
作者网站上的章节中提供了代码,其中定义了monad实例Parser.
如果你必须sat为简单Parser类型编写一个函数,我宁愿用lambda-style(as item)来完成它并完全避免monad(你注意到原来sat的do块是Parsermonad而你的是Listmonad?).我认为你的sat版本中有一个错误:而不是pih_return (fst x) inp,我认为它应该是pih_return (fst x) (snd x).
| 归档时间: |
|
| 查看次数: |
778 次 |
| 最近记录: |