我正在做一些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'
然而,第二个功能运行并完成其工作。警卫和案件之间的区别是什么?
答案 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)