问题描述
在下面的代码中,最后一句我可以把in
放在前面.它会改变什么吗?
另一个问题:如果我决定将 in
放在最后一个短语的前面,我需要缩进吗?
我试过没有缩进和拥抱抱怨
do {...} 中的最后一个生成器必须是一个表达式
导入Data.ChargroupOf _ [] = []groupOf n xs =取 n xs : groupsOf n ( tail xs )问题_8 x = 最大值.地图产品.组 5 $ xmain = do t <- readFile "p8.log"让数字 = 映射 digitToInt $concat $lines t打印 $problem_8 位数字
编辑
好的,所以人们似乎不明白我在说什么.让我改写:鉴于上述上下文,以下两个是否相同?
1.
letdigits = map digitToInt $concat $lines t打印 $problem_8 位数字
2.
letdigits = map digitToInt $concat $lines t打印中 $problem_8 位数字
关于let
中声明的绑定范围的另一个问题:我阅读了这里:
where
子句.
有时将绑定范围限定在几个受保护的方程上很方便,这需要一个 where 子句:
f x y |y>z = ...|y==z = ...|y<z = ...其中 z = x*x
请注意,这不能通过 let 表达式完成,它仅作用于它包含的表达式.
我的问题:所以,变量数字不应该对最后一个打印短语可见.我在这里错过了什么吗?
Short answer: 使用 let
而没有 in
do-block,以及列表推导式中 |
之后的部分.在其他任何地方,使用 let ... in ...
.
关键字 let
在 Haskell 中以三种方式使用.
第一种形式是一个 let 表达式.
let variable = expression in expression
这可以在任何允许使用表达式的地方使用,例如
>(让 x = 2 in x*2) + 37
第二个是 let 语句.这种形式只在do-notation内部使用,不使用
in
.do 语句让变量 = 表达式声明
第三个类似于数字 2,用于列表推导式中.同样,没有
in
.>[(x, y) |x
这种形式绑定了一个变量,该变量在后续生成器和
|
之前的表达式中的范围内.
你在这里混淆的原因是表达式(正确类型的)可以用作 do-block 中的语句,而
>let .. in ..
只是一个表达式.
由于haskell的缩进规则,比前一行缩进的一行意味着它是前一行的延续,所以这个
让 x = 42 in富
被解析为
do (让 x = 42 in foo)
没有缩进,你会得到一个解析错误:
do (让 x = 42 in)富
总而言之,永远不要在列表推导式或 do-block 中使用 in
.这是不必要的和令人困惑的,因为这些结构已经有自己的 let
形式.
In the following code, the last phrase I can put an in
in front. Will it change anything?
Another question: If I decide to put in
in front of the last phrase, do I need to indent it?
I tried without indenting and hugs complains
import Data.Char
groupsOf _ [] = []
groupsOf n xs =
take n xs : groupsOf n ( tail xs )
problem_8 x = maximum . map product . groupsOf 5 $ x
main = do t <- readFile "p8.log"
let digits = map digitToInt $concat $ lines t
print $ problem_8 digits
Edit
Ok, so people don't seem to understand what I'm saying. Let me rephrase:are the following two the same, given the context above?
1.
let digits = map digitToInt $concat $ lines t
print $ problem_8 digits
2.
let digits = map digitToInt $concat $ lines t
in print $ problem_8 digits
Another question concerning the scope of bindings declared in let
: I read here that:
Sometimes it is convenient to scope bindings over several guarded equations, which requires a where clause:
f x y | y>z = ...
| y==z = ...
| y<z = ...
where z = x*x
Note that this cannot be done with a let expression, which only scopes over the expression which it encloses.
My question: so, the variable digits shouldn't be visible to the last print phrase. Do I miss something here?
Short answer: Use let
without in
in the body of a do-block, and in the part after the |
in a list comprehension. Anywhere else, use let ... in ...
.
The keyword let
is used in three ways in Haskell.
The first form is a let-expression.
let variable = expression in expression
This can be used wherever an expression is allowed, e.g.
> (let x = 2 in x*2) + 3 7
The second is a let-statement. This form is only used inside of do-notation, and does not use
in
.do statements let variable = expression statements
The third is similar to number 2 and is used inside of list comprehensions. Again, no
in
.> [(x, y) | x <- [1..3], let y = 2*x] [(1,2),(2,4),(3,6)]
This form binds a variable which is in scope in subsequent generators and in the expression before the
|
.
The reason for your confusion here is that expressions (of the correct type) can be used as statements within a do-block, and let .. in ..
is just an expression.
Because of the indentation rules of haskell, a line indented further than the previous one means it's a continuation of the previous line, so this
do let x = 42 in
foo
gets parsed as
do (let x = 42 in foo)
Without indentation, you get a parse error:
do (let x = 42 in)
foo
In conclusion, never use in
in a list comprehension or a do-block. It is unneccesary and confusing, as those constructs already have their own form of let
.
这篇关于在 Haskell 中,我们什么时候使用 in 和 let?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!