Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange pattern-matching: is it correct?

Why does this function always succeed? It always returns True with any values and any types. Is this the correct behavior?

f a b = case a of b -> True; _ -> False
like image 811
RandomB Avatar asked Jul 29 '19 09:07

RandomB


2 Answers

The b in the case definition is not the b in in the head of the f definition. You created a new locally scoped variable. Your code is thus equivalent to:

f a b = case a of
    c -> True
    _ -> False

Pattern matching with a variable indeed always succeeds.

If you want to check if two values are the same, you will need to define some function (or let Haskell automatically derive Eq for example).

Note: you can turn on the -Wname-shadowing warning to let the compiler warn you about creating identifiers that shadow existing ones. For example your code will produce:

Prelude> f a b = case a of b -> True; _ -> False

<interactive>:1:19: warning: [-Wname-shadowing]
    This binding for ‘b’ shadows the existing binding
      bound at <interactive>:1:5
like image 121
Willem Van Onsem Avatar answered Oct 28 '22 20:10

Willem Van Onsem


Just in addition to the perfect answer accepted, my two cents:

this:

f a b = case a of b -> True; _ -> False -- (A)

and this:

f a b = case a of
                c -> True
                _ -> False --(B)

are is equivalent to:

f a b = case a of
    _ -> True

or

f a b = True

or

f _ b = True

So, be careful because that's the real behavior you created, a function that takes two parameters and returns always True.

Also:

(A) and (B) will show this warning if -Woverlapping-patterns is used:

warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In a case alternative: _ -> ...
  |
3 |               _ -> False
  |               ^^^^^^^^^^
like image 43
A Monad is a Monoid Avatar answered Oct 28 '22 20:10

A Monad is a Monoid