如何在where子句中使用来自do块赋值行的变量?

5
我有如下的代码示例:

我有以下代码示例:

{-# LANGUAGE ScopedTypeVariables #-}

main = do
  putStrLn "Please input a number a: "
  a :: Int  <- readLn
  print a

  putStrLn "Please input a number b: "
  b :: Int  <- readLn
  print b

  putStrLn ("a+b+b^2:" ++ (show $ a+b+c))
    where c = b^2

由于某种原因,我无法在where子句中使用变量b,我得到的错误如下:

Main3.hs:13:15: error: Variable not in scope: b
   |
13 |     where c = b^2
   |               ^

有什么想法可以使得bwhere子句中可用吗?


2
大致来说,where 关键字与最后一个 = 符号(或一组 guards)相关联,因此您的代码解析为 main = (do ....) where c=b^2,从而触发错误。使用 where 无法修复它,因为 expression where x=.. 不是表达式。我们需要使用 let - chi
1个回答

15

使用let代替where

{-# LANGUAGE ScopedTypeVariables #-}

main = do
  putStrLn "Please input a number a: "
  a :: Int  <- readLn
  print a

  putStrLn "Please input a number b: "
  b :: Int  <- readLn
  print b

  let c = b^2
  putStrLn ("a+b+b^2:" ++ (show $ a+b+c))
问题的原因是where子句中的变量在整个main作用域内都是可见的,但是b直到b :: Int <- readLn之后才能被访问。通常情况下,where子句不能引用在do块内绑定的变量(或者在等号右边的任何地方绑定的变量,例如f x = y*2 where y = x+1是可以的,但是f = \x -> y*2 where y = x+1不行)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接