- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 haskell 的初学者,试图理解 Let vs Where wiki page 。最后有一个示例,在函数定义 fib
的左侧添加参数 x
会更改语义。
fib1 =
let fib' 0 = 0
fib' 1 = 1
fib' n = fib1 (n - 1) + fib1 (n - 2)
in (map fib' [0 ..] !!)
fib2 x =
let fib' 0 = 0
fib' 1 = 1
fib' n = fib2 (n - 1) + fib2 (n - 2)
in map fib' [0 ..] !! x
wiki 页面指出“在第二种情况 [fib2
] 中,fib' 会为每个参数 x 重新定义”。我正在寻找一个适合初学者的解释,解释为什么会发生这种情况,一般来说,是否还有更多这样的隐藏副作用?
维基页面还有一个关于 eta reduction 的解释的链接,它表明表达式及其 eta 约简是等价的。那么,如果 fib2
是 fib1
的 eta 抽象,为什么它们不等价呢?
最佳答案
你的最后一点也许是最重要的 - fib1
和 fib2
确实是 eta 等价的,并且编译器完全可以自由地将一种转变为另一种。由于这种转换对指称语义没有影响,只影响操作语义,因此如果它“改进”了程序的操作语义,则通常将其称为优化。问题是很难说出“改进”的真正含义。
维基页面指出
The compiler cannot know whether you intended this -- while it increases time complexity it may reduce space complexity.
确实如此 - 一般来说,这种“优化”可能不是优化,具体取决于您衡量性能的方式。因此,一般来说,编译器不会执行此优化,如果程序员愿意,则将这样做的负担留给程序员,除非确实确定它确实会提高代码的性能。
这种差异是一种称为共享的特征。在 fib1
中,map fib'
中的 fib'
调用将在 fib1
内部的不同调用之间共享fib'
函数。这意味着只要计算函数,就必须保留整个列表map fib' [0..n]
。在某些情况下,这可能会降低性能,但在这种情况下,它可以为您节省大量递归函数调用。在 fib2
中,每个 map fib'
都是单独计算的,因为参数位于 let
之外。考虑这个程序,即使没有优化,它也相当于 fib1
:
fib3 :: Int -> Integer
fib3 =
let fib' 0 = 0
fib' 1 = 1
fib' n = fib1 (n - 1) + fib1 (n - 2)
in \x -> map fib' [0 ..] !! x
\x -> ..
的位置至关重要 - 这里是 let fib' = .. in\x -> map fib' ..
但是在 fib2
中,它是 \x -> let fib' = .. in map fib' ..
.
Thus it will not float the definition out from under the binding of x.
这显然取决于您使用的特定编译器以及编译程序的方式!我假设这个 wiki 页面是在编译器不够智能来找出这个特定示例的时候编写的,但是使用 GHC 7.10.3 和 -O2
,编译器实际上生成 这两个程序的代码相同。
如果您在没有优化的情况下进行编译或解释,性能差异将变得显而易见。这不是由于单态限制 - 即使您为函数提供单态类型,它仍然存在:
fib1 :: Int -> Integer
fib1 = ..
fib2 :: Int -> Integer
fib2 x = ..
区别很明显:
>:set +s
>fib2 32
2178309
(10.86 secs, 6,063,137,456 bytes)
>fib1 32
2178309
(0.00 secs, 0 bytes)
关于haskell - 在haskell中函数定义的LHS中添加参数的语义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36867004/
我知道 a = val1 if condition else val2 但是有没有办法做类似的事情 a if condition else b = val 抛出一个SyntaxError(我想这是可以
我遇到了一些归结为以下内容的代码: enum BAR { /* enum values omitted */ } class Foo{ public: void set(const BAR& ba
我是 R 新手,我想用 *apply 改进以下脚本函数(我已经阅读了 apply ,但我无法使用它)。我想用lm在多个自变量(数据框中的列)上运行。我用了 for (i in (1:3) { as
我知道要问这种有趣的问题。我想知道这是否可以做到? Class foo { public static void main(String [] args){ for (int i=0; i = new
分配给表达式(而不是名称)在 Python 中很常见。例如,这是完全有效的语法: my.object["with_some"].very_long["expression"] = func(my.ob
我想在 R 中的一行中分配多个变量。可以这样做吗? values # initialize some vector of values (a, b) = values[c(2,4)] # assign
以下程序的输出未给出预期结果: #include int main() { int *x; int *y; *x = 10; *y = 45; printf
我正在学习流口水并试图了解最佳实践。之间有什么实际区别: when $event : Event(Helper.notNull(foo),...) 和 when $event : Ev
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 7 年前。 Improve
给出以下类: template class table2D { ... public: bool copy(int r, int c, int rows , int cols, ta
我知道以下关于引用 例如。 int &ref=x;然后 ref 和 x 是内存中相同位置的名称。与指针不同,内存不是为引用分配的。 我正在使用我成功编写的引用在 C++ 中编写一个简单的交换程序。 然
尝试在 Python + Gurobi 中实现指标约束,其中指标(LHS)是二元决策变量的总和。 嗨,我想在 Python + Gurobi 中实现以下功能: Y_i_d and U_d are bi
假设我有这样的代码: #include "boost/thread/mutex.hpp" using boost::mutex; typedef mutex::scoped_lock lock; mu
这个问题在这里已经有了答案: In f(x), can x be evaluated before f? (2 个答案) 关闭 5 年前。 我已阅读 Order of evalution来自cppr
我正在学习 C++ 异常,我想对场景进行一些说明: T function() throw(std::exception); ... T t = value; try { t = function();
有谁知道 Mathematica 中是否有一个内置函数来获取降值规则的 lhs(没有任何持有)?我知道如何编写代码来做到这一点,但对于内置的 例如: a[1]=2; a[2]=3; BuiltInID
我碰巧真的很喜欢 Markdown(可能是因为 SO)而且我喜欢用 Haskell 编程。我最近发现了Literate Haskell (LHS) 我想同时使用 Markdown 和 LHS。让我给你
我想从 arules 生成的规则中提取 lhs 项。 例如, {a,b,c} => {d} 我希望能够提取 a,b,c 并将其放入字符向量中,以便我可以根据这些项目进行迭代和进一步处理。 目前,我可以
sap.ui.core.Control.extend("control.linechart", { /* the control API */ metadata : {
我正在尝试编写一个使用迭代深化算法来解决规划问题的 CLIPS 程序。出于同样的原因,我想保持较低的分支因子。 在以下代码中?s是表示树的级别的变量;我想使用一个规则来进行不同的检查。这就是我试图做的
我是一名优秀的程序员,十分优秀!