Haskell 不严格和懒惰有何不同?
我经常读到,懒惰与不严格不一样,但我发现很难理解两者的区别。它们似乎可以互换使用,但我知道它们有不同的含义。我希望有人能帮助我理解其中的差异 我有一些关于这篇文章的问题。我将在这篇文章的最后总结这些问题。我有几个示例片段,我没有测试它们,我只是将它们作为概念呈现。我添加了引号以避免您查找它们。也许这会在以后的问题上对其他人有所帮助 非严格定义: 函数f被称为严格函数,当应用于非终结符时 表达式,它也无法终止。换句话说,f是严格的 如果f bot的值为|。对于大多数编程语言,所有 功能是严格的。但哈斯克尔却不是这样。简单地说 例如,考虑CONT1,常数1函数,定义为: 常数1 x=1 Haskell中const1 bot的值为1。从操作上讲,自从 const1不“需要”其参数的值,它从不试图 对它进行评估,这样就永远不会陷入非终止状态 计算。因此,非严格函数也被称为 “惰性函数”,并被称为“惰性地”评估其参数, 或者“根据需要” - 我真的很喜欢这个定义。这似乎是我所能找到的最好的解释。Haskell 不严格和懒惰有何不同?,haskell,definition,lazy-evaluation,Haskell,Definition,Lazy Evaluation,我经常读到,懒惰与不严格不一样,但我发现很难理解两者的区别。它们似乎可以互换使用,但我知道它们有不同的含义。我希望有人能帮助我理解其中的差异 我有一些关于这篇文章的问题。我将在这篇文章的最后总结这些问题。我有几个示例片段,我没有测试它们,我只是将它们作为概念呈现。我添加了引号以避免您查找它们。也许这会在以后的问题上对其他人有所帮助 非严格定义: 函数f被称为严格函数,当应用于非终结符时 表达式,它也无法终止。换句话说,f是严格的 如果f bot的值为|。对于大多数编程语言,所有 功能是严格的。但
const1 x=1
也是懒惰的吗
非严格性意味着减少(非严格性的数学术语)
评估)由外而内的收益
如果你有(a+(bc)),那么首先你减少+,然后你减少
内河(公元前)
-
Haskell维基真让我困惑。我理解他们对订单的看法,但我不明白如果订单通过,那么(a+(b*c))
将如何进行非严格评估
在非严格求值中,函数的参数不求值
除非它们实际用于功能体的评估
在Church编码下,运算符的惰性求值映射到非严格
评价职能;因此,不严格的评估是必要的
通常被称为“懒惰”。布尔表达式在许多语言中使用
一种称为短路评估的非严格评估形式,其中
一旦可以确定一个明确的
布尔值将产生-例如,在析取表达式中
遇到true,或在连接表达式中遇到false
遇到,等等。条件表达式也通常使用
惰性求值,在这种情况下,求值会在无歧义的
分支将产生结果
-
惰性定义:
另一方面,惰性评估意味着只评估
需要其结果时的表达式(注意从
“减少”为“评估”)。因此,当评估引擎看到
表达式它构建包含任何值的thunk数据结构
计算表达式所需的,以及指向
表达本身。当实际需要评估结果时
引擎调用表达式,然后将thunk替换为
结果供将来参考。
很明显,砰的一声和砰的一声之间有很强的对应关系
部分计算表达式。因此,在大多数情况下,术语“懒惰”和
“不严格”是同义词。但不完全如此
-
这似乎是哈斯克尔特有的答案。我认为,懒惰意味着重击,不严格意味着部分评估。这种比较是否过于简单?懒惰是否始终表示thunks,而不严格是否始终表示部分评估
在编程语言理论中,延迟求值或按需调用是非常重要的
延迟表达式求值的求值策略
直到实际需要其值(非严格评估)以及
避免重复评估(共享)
-
命令式示例
我知道大多数人在学习函数式语言时都会说忘记命令式编程。然而,我想知道这些是否符合非严格、懒惰、两者都有或两者都没有的条件?至少它会提供一些熟悉的东西
短路
f1() || f2()
C#、Python和其他带有“yield”的语言
问题
我知道答案就在我面前,有那么多的资源,但我无法把握。这一定义似乎太容易被视为暗示或明显而不予理睬
我知道我有很多问题。请随时回答您认为相关的任何问题。我添加了这些问题供讨论
也是懒惰的吗const1 x=1
- 如何从“内向”非严格评估?是否因为向内允许减少不必要的表达式,如
?减少似乎符合懒惰的定义const1 x=1
- 懒惰是否总是意味着thunks和不严格是否总是意味着部分评估?这只是一个概括吗
- 以下命令式概念是懒惰的、不严格的、两者都有还是两者都没有?
- 短路
- 使用收益率
- 传递回调以延迟或避免执行
- 是懒惰的非严格的
谢谢你 如果我们说的是一般的计算机科学术语,那么“懒惰”和“不严格”通常是同义词——它们代表相同的总体理念,在不同的情况下以不同的方式表达 然而,在特定的专业背景下
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
int f1() { return 1;}
int f2() { return 2;}
int lazy(int (*cb1)(), int (*cb2)() , int x) {
if (x == 0)
return cb1();
else
return cb2();
}
int eager(int e1, int e2, int x) {
if (x == 0)
return e1;
else
return e2;
}
lazy(f1, f2, x);
eager(f1(), f2(), x);
f1() || f2()
int f1() { return 1;}
int f2() { return 2;}
int lazy(int (*cb1)(), int (*cb2)() , int x) {
if (x == 0)
return cb1();
else
return cb2();
}
int eager(int e1, int e2, int x) {
if (x == 0)
return e1;
else
return e2;
}
lazy(f1, f2, x);
eager(f1(), f2(), x);