哈斯克尔:哪里与让 [英] Haskell: Where vs. Let

查看:187
本文介绍了哈斯克尔:哪里与让的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Haskell的新手,我非常困惑 Where 。他们似乎都提供了类似的目的。我已阅读哪里之间的一些比较,但我无法辨别何时使用每个比较。是否有人可以提供一些上下文,或者可以举几个例子说明何时使用另一种情况?


Where VS Let



A 其中子句只能在函数定义的级别定义。通常,这与 let 定义的范围相同。 唯一的区别是当警卫被使用时其中子句涵盖所有警卫的范围。相反, let 表达式的范围只是当前的函数子句和守卫(如果有的话)。


Haskell备忘单



Haskell Wiki 非常详细,并提供了各种案例,但它使用了假设的示例。我发现它对于初学者的解释过于简单。



让的优势

  f :: State sa 
f = State $ \x - > y
其中y = ... x ...

Control.Monad.State


将不起作用,因为where引用了
模式匹配f =,其中没有x
在范围内。相反,如果您有
开始让,那么您不会
有麻烦。


< a href =http://www.haskell.org/haskellwiki/Let_vs._Where#Advantages_of_let =noreferrer> Haskell Wiki关于Let的优点

  f :: State sa 
f = State $ \x - >
let y = ... x ...
in y

Where的优势

  fx 
| cond1 x = a
| cond2 x = g a
|否则= f(h x a)
其中
a = w x

f x
= let a = w x

_ cond1 x = a
| cond2 x = g a
|否则= f(hxa)

声明与表达



Haskell wiki提到 子句是声明性的,而表达式是表达性的。除了风格,他们的表现如何不同?

 声明风格|表达式样式
-------------------------------------- + ---- -----------------------------------------
where子句|让表达式
参数LHS:f x = x * x | Lambda抽象:f = \ x - > x * x
模式匹配:f [] = 0 |情况表达式:f xs = []的情况xs - > 0
近卫:f [x] | x> 0 ='a'|如果表达式:f [x] = if x> 0,那么'a'else ...




  1. 在第一个示例中,为什么在作用域中,而其中不是?

  2. 在第一个示例中应用 Where

  3. 是否可以将这个应用于其中变量代表实际表达式的实例?

  4. 什么时候使用每个规则有一个通用的经验法则?






更新



对于那些稍后通过此线程发布的信息,我发现了最佳解释:


设置表达式。



Haskell的let表达式是有用的
,只要一组嵌套绑定是
所需的。作为一个简单的例子,
考虑:

  let y = a * b 
fx =(x + y )/ y
in fc + fd

由let $ b创建的一组绑定$ b表达式是相互递归的,并且
模式绑定被视为懒惰
模式(即它们带有隐式
〜)。唯一允许的
类型的声明是类型签名,
函数绑定以及
绑定模式。


Where子句。



有时,将
绑定范围限制在几个有保护的
等式,它需要一个
子句:

  fxy | y> z = ... 
| y == z = ...
| y< z = ...
其中z = x * x

请注意,用一个let表达式来完成,这个表达式只覆盖它所包含的表达式。 where子句只允许在一组方程或案例表达式的顶层。 let表达式中绑定的相同属性和约束适用于where子句中的绑定。这两种形式的嵌套范围看起来非常相似,但请记住let表达式是一个表达式,而where子句不是 - 它是函数声明和case表达式语法的一部分。



1:示例中的问题

  f :: State sa 
f = State $ \x - > y
其中y = ... x ...

是参数 X 其中子句只能引用函数 f (没有)和外部函数的参数



<2>要在第一个示例中使用其中,您可以引入第二个命名函数
x 作为参数,如下所示:

  f =州f'
f'x = y
其中y = ... x ...

或者像这样:

  f = f'
其中
f 'x = y
其中y = ... x ...



<3>:这里是一个没有 ... 的完整示例:

  module StateExample其中

data State as = State(s - >(a,s))

f1 :: State Int(Int,Int)
f1 = State $ \state @(a,b) - >
let
hypot = a ^ 2 + b ^ 2
result =(hypot,state)
结果

f2 :: State Int(Int ,Int)
f2 =状态f
其中
f state @(a,b)= result
其中
hypot = a ^ 2 + b ^ 2
result =(hypot,state)

4:何时使用 let 其中是品味的问题。我使用 let 来强调一个计算(通过将它移到前面)和其中强调程序流移动计算到后面)。

I am new to Haskell and I am very confused by Where vs. Let. They both seem to provide a similar purpose. I have read a few comparisons between Where vs. Let but I am having trouble discerning when to use each. Could someone please provide some context or perhaps a few examples that demonstrate when to use one over the other?

Where vs. Let

A where clause can only be defined at the level of a function definition. Usually, that is identical to the scope of let definition. The only difference is when guards are being used. The scope of the where clause extends over all guards. In contrast, the scope of a let expression is only the current function clause and guard, if any.

Haskell Cheat Sheet

The Haskell Wiki is very detailed and provides various cases but it uses hypothetical examples. I find its explanations too brief for a beginner.

Advantages of Let:

f :: State s a
f = State $ \x -> y
   where y = ... x ...

Control.Monad.State

will not work, because where refers to the pattern matching f =, where no x is in scope. In contrast, if you had started with let, then you wouldn't have trouble.

Haskell Wiki on Advantages of Let

f :: State s a
f = State $ \x ->
   let y = ... x ...
   in  y

Advantages of Where:

f x
  | cond1 x   = a
  | cond2 x   = g a
  | otherwise = f (h x a)
  where
    a = w x

f x
  = let a = w x
    in case () of
        _ | cond1 x   = a
          | cond2 x   = g a
          | otherwise = f (h x a)

Declaration vs. Expression

The Haskell wiki mentions that the Where clause is declarative while the Let expression is expressive. Aside from style how do they perform differently?

Declaration style                     | Expression-style
--------------------------------------+---------------------------------------------
where clause                          | let expression
arguments LHS:     f x = x*x          | Lambda abstraction: f = \x -> x*x
Pattern matching:  f [] = 0           | case expression:    f xs = case xs of [] -> 0
Guards:            f [x] | x>0 = 'a'  | if expression:      f [x] = if x>0 then 'a' else ...

  1. In the first example why is the Let in scope but Where is not?
  2. Is it possible to apply Where to the first example?
  3. Can some apply this to real examples where the variables represent actual expressions?
  4. Is there a general rule of thumb to follow when to use each?


Update

For those that come by this thread later on I found the best explanation to be found here: "A Gentle Introduction to Haskell".

Let Expressions.

Haskell's let expressions are useful whenever a nested set of bindings is required. As a simple example, consider:

let y   = a*b
    f x = (x+y)/y
in f c + f d

The set of bindings created by a let expression is mutually recursive, and pattern bindings are treated as lazy patterns (i.e. they carry an implicit ~). The only kind of declarations permitted are type signatures, function bindings, and pattern bindings.

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. A where clause is only allowed at the top level of a set of equations or case expression. The same properties and constraints on bindings in let expressions apply to those in where clauses. These two forms of nested scope seem very similar, but remember that a let expression is an expression, whereas a where clause is not -- it is part of the syntax of function declarations and case expressions.

解决方案

1: The problem in the example

f :: State s a
f = State $ \x -> y
    where y = ... x ...

is the parameter x. Things in the where clause can refer only to the parameters of the function f (there are none) and things in outer scopes.

2: To use a where in the first example, you can introduce a second named function that takes the x as a parameter, like this:

f = State f'
f' x = y
    where y = ... x ...

or like this:

f = State f'
    where
    f' x = y
        where y = ... x ...

3: Here is a complete example without the ...'s:

module StateExample where

data State a s = State (s -> (a, s))

f1 :: State Int (Int, Int)
f1 = State $ \state@(a, b) ->
    let
        hypot = a^2 + b^2
        result = (hypot, state)
    in result

f2 :: State Int (Int, Int)
f2 = State f
    where
    f state@(a, b) = result
        where
        hypot = a^2 + b^2
        result = (hypot, state)

4: When to use let or where is a matter of taste. I use let to emphasize a computation (by moving it to the front) and where to emphasize the program flow (by moving the computation to the back).

这篇关于哈斯克尔:哪里与让的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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