我可以在“do”中使用“let”吗? [复制]

Posted

技术标签:

【中文标题】我可以在“do”中使用“let”吗? [复制]【英文标题】:Can I use "let" inside "do"? [duplicate] 【发布时间】:2021-10-22 09:51:22 【问题描述】:

这个简单的程序打印输入文件中数字列表的总和和乘积。

main :: IO ()
main = do
  text <- readFile "./input.txt"
  print $ sum [read line | line <- lines text]
  print $ product [read line | line <- lines text]

-

Example input:
1
2
3
4

Example output:
10
24

-

最好避免重复[read line | line &lt;- lines text]。如果我提取函数printSumAndProduct,我可以使用let 表达式来执行此操作:

main :: IO ()
main = do
  text <- readFile "./input.txt"
  printSumAndProduct text

printSumAndProduct :: String -> IO ()
printSumAndProduct text =
  let numbers = [read line | line <- lines text]
  in do
    print $ sum numbers
    print $ product numbers

但是,我更喜欢只有一个函数,main是否可以在没有单独的函数printSumAndProduct 的情况下做到这一点?

这是我尝试过的:

main :: IO ()
main = do
  text <- readFile "./input.txt"
  let numbers = [read line | line <- lines text]
  in do
    print $ sum numbers
    print $ product numbers

但这是一个语法错误:

main.hs:5:3: error: parse error on input ‘in’

【问题讨论】:

(也许有更好的副本-但关键点显示在已接受答案的点“2”中:在do 内,您可以简单地使用let“声明”而不用in) 啊——我想是的,谢谢! 只需在最后一个“in”关键字的左侧再插入一个空格,它就会编译。缩进规则有一些微妙之处。似乎在那种情况下(做构造)“in”子句必须从属于“let”子句。请参阅 user395760 在重复问题中的回答。 @jpmariner 与 in 从属于 let 子句无关;整个let ... in 表达式对缩进不敏感(其中的绑定块是,但如果in 部分无关紧要,则缩进)。问题是每行缩进以匹配 do 块中语句的对齐方式都被视为块中 new 语句的开始,而 do 块语句可以'不要以in开头。 .... 所以我们还应该注意,使用显式的 ; 分隔符将消除所有此类由缩进引起的问题。为了可读性,我们仍然应该使用良好的缩进,但如果我们稍微偏离它仍然可以工作:do x &lt;- xs ; let a = b; c = d ; y &lt;- ys ; foo x a c y . 【参考方案1】:

通过Robin Zigmond的评论链接In Haskell, when do we use in with let?:

main :: IO ()
main = do
  text <- readFile "./input.txt"
  let numbers = [read line | line <- lines text]
  print $ sum numbers
  print $ product numbers

【讨论】:

以上是关于我可以在“do”中使用“let”吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

您可以在带有实体框架核心的 Iqueryable 中使用带有 let 语句的字典吗?

为啥 for..of / for..in 循环可以使用 const 而普通的 for 循环在 JS 中只能使用 let 或 var 作为其变量? [复制]

ES6系列,1.新增let和const命令

Python中有“做......直到”吗? [复制]

在 OCaml 中的 let 命令(即 let _ = ... in)中使用下划线通配符有啥副作用吗?

不使用 in 时 let 的范围是啥?