Strange pattern-matching: is it correct?

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

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
  |               ^^^^^^^^^^