【发布时间】: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 <- 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 <- xs ; let {a = b; c = d} ; y <- ys ; foo x a c y }.
标签: haskell