首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >sat函数中出现"Programming In Haskell“错误

sat函数中出现"Programming In Haskell“错误
EN

Stack Overflow用户
提问于 2010-04-09 20:52:00
回答 4查看 842关注 0票数 5

我在Graham Hutton的Haskell编程的第8章中,我正在复制代码并在GHC中测试它。

请在此处查看幻灯片:http://www.cis.syr.edu/~sueo/cis352/chapter8.pdf特别是幻灯片15

到目前为止我复制的相关代码是:

代码语言:javascript
复制
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

我已经将return函数的名称从书中更改为pih_return,这样它就不会与Prelude return函数冲突。

错误在最后一个函数sat中。这是我直接从书上抄来的。

正如你可能看到的,p是一个从CharBool的函数(例如isDigit),而x[(Char, String)]类型的,所以这是第一个错误。

然后pih_return接受一个值v并返回[(v, inp)],其中inp是一个String。这会在sat中导致错误,因为传递的vx,而不是Char

通过将inp显式地包含到sat中,我提出了这个解决方案

代码语言:javascript
复制
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

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-04-09 21:45:16

第一个sat不能工作,Parser必须是monad才能使用do表示法。为了使其成为monad实例,必须使用newtype

我并不拥有这本书,但我猜作者想从一个简单的解析器类型开始,然后将其扩展到一个完整的Parser,我怀疑您将非一元版本的定义与monad monad之一(sat)混淆了,并在此过程中错过了monad实例声明。

这里有可用on the author's web site一章中的代码,其中为Parser定义了一个monad实例。

如果您必须为简单的Parser类型编写sat函数,我宁愿使用lambda风格(如item),并且完全避免使用monad(您注意到最初的satdo块是Parsermonad,而您的是List monad?)。我认为您的sat版本中有一个bug :我认为它应该是<do>d17Parser>。

票数 5
EN

Stack Overflow用户

发布于 2010-04-10 09:32:49

如果没有monad,就不能使用do表示法;除非使用datanewtype,否则不能创建monad实例;如果不引入烦人的值构造函数,就不能使用datanewtype。毫无疑问,值构造函数被省略了,因为它很烦人。

在下面的示例中,您可以看到我使用了newtype并引入了烦人的值构造函数Parser。这就是instance声明工作的原因,此时您不仅可以使用do-notation,还可以使用标准的一元returnfail

此代码编译时不会出现错误或警告:

代码语言:javascript
复制
module P
where

newtype Parser a = Parser (String -> [(a, String)])
instance Monad Parser where
  return a = Parser $ \inp -> [(a, inp)]
  fail _   = Parser $ \_   -> []
  Parser f >>= k = Parser $ \inp -> 
     [(b, inp'') | (a, inp') <- f inp, let Parser g = k a, (b, inp'') <- g inp']

item :: Parser Char
item = Parser $ \inp -> case inp of
                          [] -> []
                          (x:xs) -> [(x,xs)]
parse :: Parser a -> String -> [(a, String)]
parse (Parser p) inp = p inp
sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           if p x then return x else fail "predicate not satisfied"
票数 2
EN

Stack Overflow用户

发布于 2010-04-09 21:45:59

这些幻灯片缺少Parser类型的Monad类型类的实现。

使用该声明,do表示法是正确的;x <- item实际上执行了从[(Char, String)](Char, String)的正确解包。

如果不编译它来查看错误,我似乎无法获得这个定义,但这是一个开始:

代码语言:javascript
复制
instance Monad (Parser a) where
  return x = pih_return x
  -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b
  p >>= f = \inp -> case p inf of
                      [] -> []
                      (x:xs) -> (f x) xs -- this line is probably wrong
  fail message = [] -- message is ignored
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2607498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档