这是我的代码的简化版本:
data Exp = Var String
test :: Exp -> String -> Bool
test e vIn = case e of
Var vIn -> True
_ -> False
当我运行时:
test (Var "X") "Y"
我得到了真,这很奇怪,因为它需要匹配(Var vIn)和(Var s),s~ = vIn。
任何人都可以解释发生了什么,并建议一种解决方法吗?
答案 0 :(得分:8)
Haskell不允许匹配模式中的变量,因为这需要这些变量的类型是Eq
的实例。例如,这不起作用
isEqual :: Int -> Int -> Bool
isEqual a a = True
isEqual _ _ = False
它给出错误:
Conflicting definitions for `a'
...
In an equation for `isEqual
如果Haskell不允许这样的事情,为什么你的例子编译呢?您的代码中发生的事情是vIn
语句中的case
变量阴影 vIn
变量绑定在等式中进行测试。如果使用-Wall
标志进行编译,编译器也会对此发出警告:
code.hs:7:18: Warning:
This binding for `vIn' shadows the existing binding
bound at code.hs:6:8
这意味着两个 vIn
变量不相等,只有内部变量可见,因为它会影响外部变量。
要修复代码,您必须明确地将函数参数与案例中匹配的vIn
值进行比较:
data Exp = Var String
test :: Exp -> String -> Bool
test e x = case e of
Var vIn -> vIn == x -- Explicitly compare vIn to x
_ -> False
或者只是在Var
等式的test
上使用警卫和模式匹配,如果这是一个选项:
data Exp = Var String
test :: Exp -> String -> Bool
test (Var a) vIn
| a == vIn = ... {- Code for the case that vIn == a -}
| otherwise = False
答案 1 :(得分:4)
匹配中的vIn
正在隐藏vIn
函数参数,绑定总是成功。您可以绑定到一个新变量并使用模式保护来检查值是否相等:
test e vIn = case e of
Var v | v == vIn -> True
_ -> False
或者,您可以直接与Var
匹配,而不是使用case
:
test (Var v) vIn = v == vInt