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

查看:148
本文介绍了在Haskell中,我们什么时候使用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


  1. 第一种形式是 let-expression

      let变量=表达式

    只要表达式被允许,就可以使用它,例如

     > (让x = 2 x * 2)+ 3 
    7


  2. 第二个是 let-statement 。此表单仅用于表示法中,并且不在中使用

      do语句
    let变量=表达式
    语句


  3. 第三个与第二个类似,用于列表解析中。同样,中没有

     > [(x,y)| (1,2),(2,4),(3,6)] 

    这个表单绑定一个变量,该变量在随后的生成器中和表达式之前的 |






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

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

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