Question: Here's (a simplified version of) my code:

```
data Exp = Var String

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

```

When I run this:

```
test (Var "X") "Y"

```

I get True, which is odd because it requires matching (Var vIn) and (Var s), s ~= vIn.

Can anyone explain what's going on, and suggest a way to fix it?

Answer: 
Haskell doesn't allow to match variables in patterns, because that would require the types of these variables to be an instance of `Eq`. For example, this doesn't work

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

```

It gives the error:

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

```

If Haskell doesn't allow such things, why does your example compile then? What happens in your code is that the `vIn` variable in the `case` statement *shadows* the `vIn` variable bound in the equation for test. The compiler also warns you about this if you compile with the `-Wall` flag:

```
code.hs:7:18: Warning:
This binding for `vIn' shadows the existing binding
  bound at code.hs:6:8

```

This means that there are *two* `vIn` variables, which are not equal, Only the inner one is visible, because it shadows the outer one. 

To fix the code, you'll have to explictly compare the function argument to the `vIn` value matched in the case:

```
data Exp = Var String

test :: Exp -> String -> Bool
test e x = case e of
         Var vIn -> vIn == x -- Explicitly compare vIn to x
         _       -> False

```

Or just use guards and pattern match on `Var` in the `test` equation if that's an option:

```
data Exp = Var String

test :: Exp -> String -> Bool
test (Var a) vIn
  | a == vIn = ... {- Code for the case that vIn == a -}
  | otherwise = False

```
The `vIn` in your match is shadowing the `vIn` function argument, and the binding always succeeds. You can bind to a new variable and use a pattern guard to check the values are equal:

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

```

alternatively you can match against `Var` directly instead of using `case`:

```
test (Var v) vIn = v == vInt

```