为什么警卫的行为不同于'符号?

时间:2015-11-12 14:15:35

标签: function haskell types maybe

我正在做一些haskell编程,并且在使用警卫时出现错误,当我将警卫改为'问题已经消失,我无法理解为什么会发生这种情况。我已经对我所处的情况做了一个非常简单的例子:

data Point = Point Float Float deriving (Show)  
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)

c1 :: Shape
c1 = Circle (Point 5 5 ) 12

--returns Just True if radius is bigger than 10, otherwise = Nothing
isBigger :: Shape -> Maybe Bool
isBigger (Circle _ x) 
         |x > 10 = Just True
         |otherwise = Nothing

现在,我已经完成了这两项功能(除了不同的符号,它们似乎与我完全相同): 第一:

printStuff:: Shape -> String
printStuff s1
        |isBigger s1 == Just a = show a
        |isBigger s1 == Nothing = "Not bigger than 10"   

和第二个:

printStuff2:: Shape -> String
printStuff2 s1 =
     case isBigger s1 of 
        Nothing -> "Not Bigger than 10"
        Just a -> show a

但是,带有功能的代码' PrintStuff'不会跑。错误:

不在范围内:'a'

然而,第二个功能运行并完成其工作。警卫和案件之间的区别是什么?

1 个答案:

答案 0 :(得分:4)

Guards使用布尔表达式,而case … of使用模式匹配。因此对于case,通常的模式匹配规则成立。所以你的第二个功能(几乎)与:

相同
printStuff2:: Shape -> String
printStuff2 s1 = helper (isBigger s1)
  where
    helper Nothing  = "Not Bigger than 10"
    helper (Just a) = show a
    --     ^^^^^^^
    --  pattern matching

现在,警卫最初没有模式匹配(由extensions引入)。它们只采用Bool类型的表达式:

printStuff :: Shape -> String
printStuff s1 
  | bigger == Nothing = "Not Bigger than 10"
  | otherwise         = a
 where 
   bigger   = isBigger s1
   (Just a) = bigger

请注意,如果您忘记检查bigger是否实际为Just something,则最后一次绑定会很危险。但是,使用PatternGuards,您可以使用

printStuff :: Shape -> String
printStuff s1 
  | Just a <- isBigger s1 = show a
  | otherwise             = "Not Bigger than 10"

话虽这么说,这是maybe的工作:

printStuff :: Shape -> String
printStuff s1 = maybe "Not Bigger than 10" show (isBigger s1)