繁体   English   中英

Haskell语法,解析假人的错误

[英]Haskell syntax, parse errors for dummies

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

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

除了Stephen Diehl提供的格式改进之外,还可以进行其他改进。 正如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 = ['+' , '-' , '*' , '/' , '^' , ')']

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

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获取一个空列表作为参数时你还没有真正处理过这种情况,这可能是你想要做的事情。

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

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

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

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

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 = ['+' , '-' , '*' , '/' , '^' , ')']

暂无
暂无

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

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