我是 Haskell 的新手,我很困惑Where vs. Let。它们似乎都提供了相似的目的。我读过一些比较Where vs. Let但我很难辨别何时使用它们。有人可以提供一些背景信息或者一些示例来说明何时使用其中一种而不是另一种吗?
哪里与让
A where
子句只能在函数定义级别定义。通常,这与范围相同let
定义。唯一的区别是何时使用防护装置。范围where
条款适用于所有警卫。相比之下,a 的范围let
表达式只是当前函数子句和防护(如果有)。
Haskell 备忘单 http://cheatsheet.codeslower.com/CheatSheet.pdf
The 哈斯克尔维基 http://www.haskell.org/haskellwiki/Let_vs._Where非常详细并提供了各种案例,但它使用了假设的例子。我发现它的解释对于初学者来说太简短了。
让的优点:
f :: State s a
f = State $ \x -> y
where y = ... x ...
控制单子状态 http://www.haskell.org/haskellwiki/State_Monad
不起作用,因为 where 指的是
模式匹配 f =,其中没有 x
是在范围之内。相反,如果你有
以 let 开头,然后你就不会
有麻烦。
Haskell Wiki 关于 Let 的优点 http://www.haskell.org/haskellwiki/Let_vs._Where#Advantages_of_let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
哪里的优势:
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)
声明与表达式 http://www.haskell.org/haskellwiki/Declaration_vs._expression_style
Haskell wiki 提到Where子句是声明性的,而Let表达就是表达。除了风格之外,它们的表现有何不同?
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 ...
- 在第一个例子中,为什么Let在范围内但是Where is not?
- 是否可以申请Where第一个例子?
- 有人可以将其应用于变量代表实际表达式的真实示例吗?
- 何时使用每种方法是否有可遵循的一般经验法则?
Update
对于那些后来看到这个帖子的人,我在这里找到了最好的解释:“Haskell 简要介绍 http://www.cse.iitb.ac.in/~as/fpcourse/haskell98_tutorial/patterns.html".
让表达式。
Haskell 的 let 表达式很有用
每当一组嵌套的绑定
必需的。举个简单的例子,
考虑:
let y = a*b
f x = (x+y)/y
in f c + f d
由let创建的绑定集
表达式是相互递归的,并且
模式绑定被视为惰性绑定
模式(即它们带有隐含的
〜)。唯一的声明类型
允许的是类型签名,
函数绑定和模式
绑定。
凡子句。
有时确定范围很方便
多个受保护的绑定
方程,这需要一个 where
条款:
f x y | y>z = ...
| y==z = ...
| y<z = ...
where z = x*x
请注意,这不能使用 let 表达式来完成,let 表达式仅作用于它所包含的表达式。仅允许在一组方程或 case 表达式的顶层使用 where 子句。 let 表达式中的绑定的相同属性和约束也适用于 where 子句中的绑定。这两种形式的嵌套作用域看起来非常相似,但请记住,let 表达式是表达式,而 where 子句不是——它是函数声明和 case 表达式语法的一部分。