4

这是我的代码的(简化版本):

data Exp = Var String

test :: Exp -> String -> Bool
test e vIn = case e of
                  Var vIn -> True
                  _       -> False

当我运行这个:

test (Var "X") "Y"

我得到 True,这很奇怪,因为它需要匹配 (Var vIn) 和 (Var s),s ~= vIn。

谁能解释发生了什么,并提出解决方法?

4

2 回答 2

8

Haskell 不允许匹配模式中的变量,因为这需要这些变量的类型是Eq. 例如,这不起作用

isEqual :: Int -> Int -> Bool
isEqual a a = True
isEqual _ _ = False

它给出了错误:

Conflicting definitions for `a'
...
In an equation for `isEqual

如果 Haskell 不允许这样的事情,那为什么你的例子会编译呢?在您的代码中发生的情况是,语句中的vIn变量会隐藏在待测方程中绑定的变量。如果您使用以下标志进行编译,编译器还会警告您:casevIn-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
于 2013-09-14T19:12:38.750 回答
4

匹配中的vIn正在隐藏vIn函数参数,并且绑定始终成功。您可以绑定到一个新变量并使用模式保护来检查值是否相等:

test e vIn = case e of
                  Var v | v == vIn -> True
                  _       -> False

或者,您可以直接匹配Var而不是使用case

test (Var v) vIn = v == vInt
于 2013-09-14T19:09:30.263 回答