5

I have to extract user name and email from Either of AuthResponse.

I use case of construct for it:

  let (uname, uemail) =
        case getUserResponseJSON creds of
          Right (GoogleUserResponse uname uemail) -> (uname, uemail)
          _ -> ("", "")    

But I have this warning for both uname and uemail:

    This binding for ‘uname’ shadows the existing binding
      bound at src/Foundation.hs:240:12
    |
242 |               Right (GoogleUserResponse uname uemail) -> (uname, uemail)
    |  

I expect that let (uname, uemail) is out of the scope of case of block.

How is it possible to have this warning from the case block if uname and uemail are not yet defined?

Will Ness
  • 62,652
  • 8
  • 86
  • 167
mkUltra
  • 2,382
  • 18
  • 38

3 Answers3

7

Haskell's let is actually letrec.

In let x = x in ..., the x on the right refers to the x on the left.

The scope of x, y and z in

    let 
       x = ...
       y = ...
       z = ...
    in ...

are all the code areas indicated with ....

Will Ness
  • 62,652
  • 8
  • 86
  • 167
5

How is possible to have this warning from the case block if uname and uemail still not defined?

These are defined, in the scope outside the case, two variables named uname and uemail are defined. The Haskell compiler can "tie a knot". Take for example the following expression where we define an endless list of ones:

ones :: [Int]
ones = x
    where x = 1 : x

Here we thus define a list that looks like:

+-------+
|  (:)  |<,
+---+---+ |
| o | o---'
+-|-+---+
  v
  1

So you can define a variable in terms of itself, like you do here. You do not assign a value to variable, you declare a variable. Furthermore note that the order in which you define variables is not per se the order in which you will perform operations. So it is possible that the (uname, uemail) is never evaluated, etc.

Willem Van Onsem
  • 321,217
  • 26
  • 295
  • 405
2

Ignoring the reasons, you are reimplenting Data.Either.fromRight.

import Data.Either (fromRight)

...

    let defaultResponse = GoogleUserResponse "" ""
        toTuple (GoogleUserResponse x y) = (x,y)  -- parameter names aren't important
        gResponse = fromRight defaultResponse $ getUserResponseJSON creds
        (uname, email) = toTuple gResponse

...
chepner
  • 389,128
  • 51
  • 403
  • 529