【问题标题】:My code results in parse error because of my use of guards由于我使用了警卫,我的代码导致解析错误
【发布时间】:2019-10-10 13:22:26
【问题描述】:

我有以下代码:

parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
              | s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
              | s == "+" = (Sum e e',ss'') where
                           (e,ss') = parseExpr ss
                           (e',ss'') = parseExpr ss'
              | s == "*" = (Mult e e',ss'') where
                           (e,ss') = parseExpr ss
                           (e',ss'') = parseExpr ss'

当我尝试运行它时,我收到一条错误消息“输入'|'时解析错误。它正在谈论的行是这一行:

...
                           (e',ss'') = parseExpr ss'
->            | s == "*" = (Mult e e',ss'') where
                           (e,ss') = parseExpr ss
...

我想我明白为什么了。我想这是因为我上面有两行没有被守卫屏蔽,当下面突然出现另一个守卫时,haskell 会感到困惑。但是在这些情况之后,我怎样才能添加额外的警卫呢?

我尝试过使用分号来分隔新行,但我对 Haskell 很陌生,因此不太了解它的语法。

【问题讨论】:

  • 对所有警卫使用一个位置
  • 我认为托马斯是对的。解析错误可能是因为在解析了第一个where 之后,代码会认为你的函数结束了。
  • 即使忽略解析错误,在这种情况下使用单个 where 也会减少大量重复代码。

标签: haskell syntax pattern-guards


【解决方案1】:

没有必要使用大括号(当然你可以)。但是你确实需要小心缩进。这并不像乍看起来那么难。

话虽如此,您确实不能在受保护的表达式中使用where。在这种情况下,您必须使用let,如下所示:

parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
              | s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
              | s == "+" = let (e,ss') = parseExpr ss
                               (e',ss'') = parseExpr ss'
                           in (Sum e e',ss'')
              | s == "*" = let (e,ss') = parseExpr ss
                               (e',ss'') = parseExpr ss'
                           in (Mult e e',ss'')

但是,在您的例子中,保护表达式非常简单,可以用模式匹配替换。 (建议利用这个机会。模式匹配是您在 Haskell 中最好的朋友。) 在这种情况下,您使用 where

parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
parseExpr ("-":ss) = (Min e,ss') where (e,ss') = parseExpr ss
parseExpr ("+":ss) = (Sum  e e',ss'') where (e, ss' ) = parseExpr ss
                                            (e',ss'') = parseExpr ss'

parseExpr ("*":ss) = (Mult e e',ss'') where (e, ss' ) = parseExpr ss
                                            (e',ss'') = parseExpr ss'

【讨论】:

  • 谢谢!我现在可以看到我需要更多地了解模式匹配。很好的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多