简体   繁体   English

Haskell语法,解析假人的错误

[英]Haskell syntax, parse errors for dummies

today I read a lot about Haskell but this formating is driving me crazy. 今天我读了很多关于Haskell的内容,但这种格式化让我发疯。 I want to understand my basic errors as soon as possible so I can start coding normally. 我想尽快理解我的基本错误,这样我就可以正常开始编码了。 The function here should return a string that starts with the next "math Sign" example string (2sdwds+asd)+3 should return +asd)+3 . 这里的函数应该返回一个以下一个“math Sign”示例字符串(2sdwds+asd)+3字符串(2sdwds+asd)+3应该返回+asd)+3 Here is the code 这是代码

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"

It gives me " parse error on input = ". 它给了我“输入上的解析错误=”。 I am also not sure about how exactly to call it in the main and do I really need the putStrLn function. 我也不确定如何在main中调用它,我真的需要putStrLn函数。 I don't think I need it but I tried like 2874 different ways to write this and now I just gave up and need help. 我不认为我需要它,但我尝试了2874种不同的方式来写这个,现在我放弃了,需要帮助。

Besides the improvement to formatting that Stephen Diehl provided, there are other improvements you can make. 除了Stephen Diehl提供的格式改进之外,还可以进行其他改进。 As Carl points out, you can replace the if-else if-else with guards, like so: 正如Carl指出的那样,你可以用守卫替换if-else if-else,如下所示:

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

When you're at it, you can also replace the head/tail with pattern matching, as in 当你在它时,你也可以用模式匹配替换头/尾,如

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

and if you're gonna do pattern matching, you can just as well take it all the way. 如果你要进行模式匹配,你也可以一直采用它。

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

and when you do it like this, you realise that you haven't really handled the case when getToNextSign gets an empty list as an argument, which is perhaps something you want to do. 当你这样做时,你会发现当getToNextSign获取一个空列表作为参数时你还没有真正处理过这种情况,这可能是你想要做的事情。

Here is a simpler alternative to your problem using the Prelude list functions, dropWhile and elem , which has a type sig (a -> Bool) -> [a] -> [a] . 这是使用Prelude列表函数dropWhileelem一个更简单的替代方法,它有一个sig类型(a -> Bool) -> [a] -> [a] It takes a function which will drop the elements from a list as long as the condition provided by the function is true. 它需要一个函数,只要函数提供的条件为真,就会从列表中删除元素。

Hence, your function can be rewritten as follows. 因此,您的功能可以重写如下。

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

Try to avoid explicit recursion when possible and put them higher order functions to good use. 尽可能避免显式递归,并将它们放在更高阶函数中以便充分利用。 And the Prelude has tons of list manipulation functions which come in handy all the time. Prelude有大量的列表操作功能,它们总是派上用场。

Haskell, being whitespace sensitive, has to have the body of the function indented beyond the toplevel. Haskell,对空白敏感,必须让函数的主体缩进到顶层之外。 An direct fix for your original code would be: 对原始代码的直接修复将是:

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"

As pointed out in the comments you don't need do notation here since you aren't using a monad. 正如评论中指出的那样,因为你没有使用monad,所以你不需要在这里做表示法。 The let statements can be instead be written as where statements. 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 = ['+' , '-' , '*' , '/' , '^' , ')']

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM