5

Why does the following Haskell script not work as expected?

find :: Eq a => a -> [(a,b)] -> [b]
find k t = [v | (k,v) <- t]

Given find 'b' [('a',1),('b',2),('c',3),('b',4)], the interpreter returns [1,2,3,4] instead of [2,4]. The introduction of a new variable, below called u, is necessary to get this to work:

find :: Eq a => a -> [(a,b)] -> [b]
find k t = [v | (u,v) <- t, k == u]

Does anyone know why the first variant does not produce the desired result?

6
  • Repeat after me: there are no variables in Haskell. ;-) These are symbols or identifiers. Variables imply variability. In Haskell, everything is immutable. Commented Oct 29, 2010 at 16:28
  • 9
    @Konrad Rudolph: The Haskell 98 Report uses the term "variable" all over the place. It's important to note that this doesn't mean what you might expect, but I don't think being more persnickety than the standard documentation is necessarily helpful. Commented Oct 29, 2010 at 16:31
  • 4
    @Konrad Rudolph: Surely you jest! Why, I've found a whole section about variables in some Haskell, right here. Commented Oct 29, 2010 at 16:52
  • 1
    @Travis Brown: It means pretty much the same thing it does when speaking of variables bound by a quantifier in a formula of first-order logic... can't imagine why someone would expect anything else! ;) Commented Oct 29, 2010 at 16:58
  • Reading the first version of find, I was actually expecting [1,2,3,4]... Must read the function name also. Commented Oct 29, 2010 at 19:08

3 Answers 3

14

From the Haskell 98 Report:

As usual, bindings in list comprehensions can shadow those in outer scopes; for example:

[ x | x <- x, x <- x ] = [ z | y <- x, z <- y]

One other point: if you compile with -Wall (or specifically with -fwarn-name-shadowing) you'll get the following warning:

Warning: This binding for `k' shadows the existing binding
           bound at Shadowing.hs:4:5

Using -Wall is usually a good idea—it will often highlight what's going on in potentially confusing situations like this.

Sign up to request clarification or add additional context in comments.

1 Comment

I think the issue is not about shadowing. It's about the meaning of an identifier in a pattern in the first place -- that it does not match the value of a variable with that identifier, but rather matches anything and binds the value to a new variable with that idenfier
11

The pattern match (k,v) <- t in the first example creates two new local variables v and k that are populated with the contents of the tuple t. The pattern match doesn't compare the contents of t against the already existing variable k, it creates a new variable k (which hides the outer one).

Generally there is never any "variable substitution" happening in a pattern, any variable names in a pattern always create new local variables.

Comments

3

You can only pattern match on literals and constructors.
You can't match on variables. Read more here.

That being said, you may be interested in view patterns.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.