"在Haskell中编程"在sat函数中出错

Mat*_*len 5 haskell

我在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是从功能CharBool(例如isDigit),并x为类型的[(Char, String)],所以这是第一个错误.

然后pih_return取一个值v,并返回[(v, inp)]其中inp一个String.这会导致错误,sat因为v传递的x不是a Char.

我已经提出了这个解决方案,通过明确包含inpsat

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)

这是解决问题的最佳方法吗?

Rüd*_*nke 5

第一个sat不能工作,Parser必须是monad才能使用do符号.为了使它成为monad实例,newtype必须使用它.

我不拥有这本书,但我想作者想要从一个简单的解析器类型开始,然后将它扩展为一个完整的monad,我怀疑你已将非monadic版本的定义与Parsermonad 之一混淆了(sat并且错过了沿途的monad实例声明.

作者网站上的章节中提供代码,其中定义了monad实例Parser.

如果你必须sat为简单Parser类型编写一个函数,我宁愿用lambda-style(as item)来完成它并完全避免monad(你注意到原来satdo块是Parsermonad而你的是Listmonad?).我认为你的sat版本中有一个错误:而不是pih_return (fst x) inp,我认为它应该是pih_return (fst x) (snd x).