我可以在Haskell上使用放散后卫吗?

时间:2018-10-14 10:23:24

标签: haskell

现在我有一个错误,指出输入'|'的解析错误,该错误引用了'|'在if语句之前。 我也不确定是否可以像下面的代码那样使用让守。 下面的代码是我的问题的示例,请帮助纠正我的错误,谢谢!!

func x y
   | let 
       sum = x + y
       mult = x * y
   | if sum == 3
       then do
            sum+=1
       else if mult == 5
           then do
                mult -=1

3 个答案:

答案 0 :(得分:6)

实际上,Haskell2010允许let表达式出现在后卫中。请参阅报告here|let decls向环境引入了decls中定义的名称。

对于您的情况,我们可以写

fun x y 
  | let sum = x + y, sum == 3 = Just (sum + 1)
  | let mult = x * y, mult == 5 = Just (mult - 1)
  | otherwise = Nothing

答案 1 :(得分:3)

不幸的是,我们无法使用let来做到这一点。

更准确地说,我们可以写

func x y | let z = .. in condition = result
         | otherCondition          = otherResult

但是z仅在condition中可见,而在resultotherConditionotherResult中不可见。

(这可以通过使用模式保护器来改善,但不能完全改善:zotherConditionotherResult中仍然不可用)

该解决方案改用where

  func x y | condition      = result
           | otherCondition = otherResult
           where z = ...

在这里,z随处可见。

(我个人不喜欢这种where的形式,因为它与z的使用相距太远,但是在这种情况下我看不到任何简单的替代方法。)

最后,让我补充说,您的代码对我而言似乎不起作用:在函数式编程中没有if then的情况下没有else,并且mult -= 1无法修改变量mult (对于sum += 1也是如此)。

答案 2 :(得分:3)

您可以在顶部使用let,但是必须在其后跟随in来指定要使用定义值的块。同样,您缺少有关sum /= 3mul /= 5时该怎么办的条件。因此,返回Maybe类型可能更好,例如

func :: Integral a => a -> a -> Maybe a
func x y = let sum = x + y
               mul = x * y
            in case (sum, mul) of
               (3, _) -> Just (sum + 1)
               (_, 5) -> Just (mul - 1)
               _      -> Nothing