Unexpected pattern matching behavior

Here (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 ran this:

 test (Var "X") "Y" 

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

Can someone explain what is happening and suggest a way to fix this?

+4
source share
2 answers

Haskell does not allow matching variables in templates, because for these types of types these variables must be an Eq instance. For example, this does not work.

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

It gives an error:

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

If Haskell doesn't allow such things, why does your example compile? What happens in your code is that the vIn variable in the case expression shades the vIn variable associated in the equation for the test. The compiler also warns about this if you compile 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 that are not equal, only the inside is visible because it obscures the outside.

To fix the code, you will have to explicitly compare the function argument with the vIn value, which is appropriate in the case:

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

Or just use protection and pattern matching on Var in the test equation if this is 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 
+7
source

vIn in your match obscures the argument of the vIn function, and the binding always succeeds. You can bind to a new variable and use template protection to verify that the values ​​are equal:

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

alternatively you can directly match Var instead of using case :

 test (Var v) vIn = v == vInt 
+4
source

Source: https://habr.com/ru/post/1502202/


All Articles