5

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

case of为它使用构造:

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

但我对两者都有这个uname警告uemail

    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块的范围。

如果并且尚未定义,如何从case块中获得此警告?unameuemail

4

3 回答 3

7

Haskell 的let实际上是letrec.

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

的范围x和在yz

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

是用 . 指示的所有代码区域...

于 2019-08-25T16:25:46.200 回答
5

如果 uname 和 uemail 仍未定义,如何从 case 块中获得此警告?

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

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

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

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

所以你可以定义一个变量本身,就像你在这里做的那样。您没有为变量赋值,而是声明了一个变量。此外请注意,您定义变量的顺序本身并不是您将执行操作的顺序。所以有可能(uname, uemail)永远不会评估,等等。

于 2019-08-25T15:11:15.613 回答
2

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

...
于 2019-08-25T16:03:28.127 回答