在 Haskell 中,我们什么时候使用 in 和 let? [英] In Haskell, when do we use in with let?

查看:25
本文介绍了在 Haskell 中,我们什么时候使用 in 和 let?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,最后一句我可以把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 而没有 indo-block,以及列表推导式中 | 之后的部分.在其他任何地方,使用 let ... in ....

<小时>

关键字 let 在 Haskell 中以三种方式使用.

  1. 第一种形式是一个 let 表达式.

    let variable = expression in expression

    这可以在任何允许使用表达式的地方使用,例如

    >(让 x = 2 in x*2) + 37

  2. 第二个是 let 语句.这种形式只在do-notation内部使用,不使用in.

    do 语句让变量 = 表达式声明

  3. 第三个类似于数字 2,用于列表推导式中.同样,没有 in.

    >[(x, y) |x <- [1..3],让 y = 2*x][(1,2),(2,4),(3,6)]

    这种形式绑定了一个变量,该变量在后续生成器和|之前的表达式中的范围内.

<小时>

你在这里混淆的原因是表达式(正确类型的)可以用作 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

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.

  1. 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
    

  2. 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
    

  3. 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆