Haskell语法,解析假人的错误

时间:2014-02-04 21:07:03

标签: string parsing haskell syntax

今天我读了很多关于Haskell的内容,但这种格式化让我发疯。我想尽快理解我的基本错误,这样我就可以正常开始编码了。这里的函数应该返回一个字符串,该字符串以下一个“math Sign”示例字符串(2sdwds+asd)+3开头应该返回+asd)+3。  这是代码

getToNextSign :: String -> String 
getToNextSign str = do

let mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']
let a = head str
if a `elem` mathSigns 
 then str
 else if tail str /= [] 
       then getToNextSign $ tail str
       else []

main = do
putStrLn $ getToNextSign "(2sdwds+asd)+3"

它给了我“input =的解析错误”。我也不确定如何在main中调用它,我真的需要putStrLn函数。我不认为我需要它,但我尝试了2874种不同的方法来写这个,现在我放弃了,需要帮助。

3 个答案:

答案 0 :(得分:3)

除了Stephen Diehl提供的格式改进之外,您还可以进行其他改进。正如卡尔指出的那样,你可以用警卫替换if-else if-else,如下所示:

getToNextSign :: String -> String
getToNextSign str
  | a `elem` mathSigns = str
  | tail str /= []     = getToNextSign $ tail str
  | otherwise          = []
  where
    a = head str
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

当你在它时,你也可以用模式匹配替换头/尾,如

getToNextSign :: String -> String
getToNextSign (c:cs)
  | c `elem` mathSigns = c:cs
  | not (null cs)      = getToNextSign cs
  | otherwise          = []
  where
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

如果你要进行模式匹配,你也可以一直采用它。

getToNextSign :: String -> String
getToNextSign str = case str of
     c:_ | c `elem` mathSigns -> str
     c:[] -> []
     _:cs -> getToNextSign cs
  where mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

当你这样做时,你意识到当getToNextSign获得一个空列表作为参数时你还没有真正处理过这种情况,这可能是你想做的事情。

答案 1 :(得分:3)

使用Prelude列表函数dropWhileelem,这是一个更简单的替代问题,其函数类型为(a -> Bool) -> [a] -> [a]。只要函数提供的条件为真,它就会从列表中删除元素。

因此,您的功能可以按如下方式重写。

let getNextSign x = dropWhile  ( not . `elem` "+-*/^)" ) x

尽可能避免显式递归,并将它们放在更高阶函数中以便充分利用。 Prelude有大量的列表操作功能,它们总是派上用场。

答案 2 :(得分:2)

Haskell,对于空白敏感,必须让函数的主体缩进到顶层之外。对原始代码的直接修复将是:

getToNextSign :: String -> String
getToNextSign str = do
  let mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']
  let a = head str
  if a `elem` mathSigns
   then str
   else if tail str /= []
         then getToNextSign $ tail str
         else []

main = do
  putStrLn $ getToNextSign "(2sdwds+asd)+3"

正如评论中指出的那样,你不需要在这里做记号,因为你没有使用monad。 let语句可以写成where语句。

getToNextSign :: String -> String
getToNextSign str =
  if a `elem` mathSigns
   then str
   else if tail str /= []
         then getToNextSign $ tail str
         else []
  where
    a = head str
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']