2012-03-27 67 views
3

所以我有这个计算器我正在建设,接受像“let a = 2”这样的用户变量输入这些变量存储在一个元组列表(变量,值)我需要帮助获取数据从这个列表中。到目前为止我的代码通过一个haskell列表搜索

primary :: Parser Float 
primary = do symbol "(" 
     e <- expression 
     symbol ")" 
     return e 
     +++ do v <- identifier     
       let a = (find (==(head v)) vlist) 
       return a 

我得到一个错误,因为发现返回也许,我需要它返回一个浮点数或给用户一个错误消息。我该怎么做呢?

+0

你正在寻找一个以前的答案:http://stackoverflow.com/questions/3375483/operating-on-a-return-from-a-maybe-that-c​​ontains-just – 2012-03-27 03:44:47

回答

3

我不知道在哪里vlist从何而来。它可能应该是解析器用户状态的一部分。现在,让我们假定它是一个顶级的定义:

vlist :: [(String, Float)] 
vlist = undefined -- fill in the blanks... 

我假设你正在使用Parsec。您可以将分析器简化为:

primary :: Parser Float 
primary = choice [ between (symbol "(") (symbol ")") expression 
       , do { ident <- identifier 
         ; case lookup ident vlist of 
          Nothing -> fail $ "No such identifier: " ++ ident 
          Just v -> return v 
         } 
       ] 

对于如何处理错误有几种选择。在这里,我使用了解析器monad的fail函数。这将导致解析器返回Left parserError。或者,您可以将error替换为fail,这将导致只能在IO monad中处理的错误。

注意:要添加vlist作为解析器的状态,你需要定义与该国一个新的解析器类型:

data MyParserState = MyParserState { vlist :: [(String, Float)] } 
type MyParser = CharParser MyParserState 

-- these parsers now need to return MyParser type! 
symbol :: String -> MyParser String 
identifier :: MyParser String 
expression :: MyParser Float 

primary :: MyParser Float 
primary = choice [ between (symbol "(") (symbol ")") expression 
       , do { st <- getState 
         ; ident <- identifier 
         ; case lookup ident $ vlist st of 
          Nothing -> fail $ "No such identifier: " ++ ident 
          Just v -> return v 
         } 
       ] 
+0

好的,我想我遵循你所说的话,是的,这几乎是vlist的定义。什么是选择?我不确定那是什么? – user1294469 2012-03-27 04:07:51

+1

'choice ps'试图按顺序应用列表'ps'中的解析器,直到其中一个成功。我刚刚意识到你正在使用'+++',它被'ReadP'分析器使用,而不是'Parsec'分析器。我发现'choice'比'<|>'加入的一串解析器更好,因为当它们包含较低优先级的运算符时,不需要在元素周围放置元素。 – pat 2012-03-27 04:22:56

+0

你应该使'MyParserState'成为'newtype',或者,如果你是我的话,只需使用'[(String,Float)]' – alternative 2012-03-28 15:45:53

0

也许通过case x of块像这样运行:

case find x of (Just y) -> --your code here 
       Nothing -> error "Wrong"