在Haskell中,我们什么时候使用let? [英] In Haskell, when do we use in with let?
问题描述
在下面的代码中,我可以在前面放置一个在
中的最后一个短语。它会改变什么吗?
另一个问题:如果我决定在中放置最后一个短语前的,我是否需要缩进它?
我试过没有缩进和拥抱抱怨
..}必须是表达式
import Data.Char
groupsOf _ [ ] = []
groupsOf n xs =
取n xs:groupsOf n(尾部xs)
problem_8 x =最大值。地图产品。 groupsOf 5 $ x
main = do t< - readFilep8.log
let digits = map digitToInt $ concat $ lines t
print $ problem_8 digits
编辑
好的,所以人们似乎不明白我在说什么。让我换句话说:
是以下两个相同的,考虑到上述背景?
$ b pre> let digits = map digitToInt $ concat $ lines t
print $ problem_8 digits
<2>
let digits = map digitToInt $ concat $ lines t
in print $ issue_8 digits
另一个关于在中声明的绑定范围的问题let
:我阅读这里:
其中
子句。
fxy | 有时,将绑定的范围限制在几个守护方程的范围内是很方便的, y> z = ...
| y == z = ...
| y< z = ...
其中z = x * x
请注意,使用一个let表达式,该表达式只覆盖它所包含的表达式。
我的问题:所以,变量数字不应该对最后一个打印短语可见。我在这里错过了什么?
/ code>没有在
中,并且在 |
之后的部分中,在列表中理解。任何地方,使用 let ... in ...
。 关键字 let
在Haskell中有三种使用方式。
$ b
-
第一种形式是 let-expression 。
let变量=表达式
只要表达式被允许,就可以使用它,例如
> (让x = 2 x * 2)+ 3
7
-
第二个是 let-statement 。此表单仅用于表示法中,并且不在中使用
。
do语句
let变量=表达式
语句
-
第三个与第二个类似,用于列表解析中。同样,中没有
。
> [(x,y)| (1,2),(2,4),(3,6)]
这个表单绑定一个变量,该变量在随后的生成器中和表达式之前的
| $ c $
您在这里混淆的原因是表达式(正确类型)可以用作do-block中的语句,而 let .. in ..
只是一个表达式。
由于haskell的缩进规则,比上一行缩进的行意味着它是前一行的延续,所以这
do let x = 42 in
foo
得到解析作为
do(let x = 42 in foo)
如果没有缩进,会得到一个解析错误:
do(let x = 42 in)
foo
总之,不要在中使用在列表理解或do-b中
锁。这是不必要的和混乱的,因为这些结构已经有它们自己的形式 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
Last generator in do {...} must be an expression
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:
where
Clauses.
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中,我们什么时候使用let?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!