一个绑定怎么可能隐藏在“case of”块中的现有绑定?

How is it possible that a binding shadows the existing binding in `case of` block?

我必须从 AuthResponseEither 中提取用户名和电子邮件。

我使用 case of 构造它:

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

但是我对 unameuemail 都有这个警告:

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

我预计 let (uname, uemail) 不在 case of 块的范围内。

如果 unameuemail 尚未定义,怎么可能从 case 块中获得此警告?

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

这些是定义的,在case之外的范围内,定义了两个名为unameuemail的变量。 Haskell 编译器可以“打个结”。以下面的表达式为例,我们在其中定义了一个无穷无尽的列表:

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

因此,我们在这里定义了一个如下所示的列表:

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

因此您可以根据自身定义变量,就像您在此处所做的那样。你不分配一个值给变量,你声明一个变量。此外请注意,您定义变量的顺序是 而不是 本身就是您执行操作的顺序。所以有可能 (uname, uemail) 永远不会被评估,等等

忽略原因,您正在重新实现 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

...

Haskell的let其实是letrec

let x = x in ...中,右边的x指的是左边的x

xyz

中的范围
    let 
       x = ...
       y = ...
       z = ...
    in ...

都是...表示的代码区。​​