Haskell中的高阶函数究竟可以做什么,扩展C可以';T

Haskell中的高阶函数究竟可以做什么,扩展C可以';T,c,haskell,lambda,functional-programming,higher-order-functions,C,Haskell,Lambda,Functional Programming,Higher Order Functions,GCC具有允许使用嵌套函数的功能 实际上,我不明白Haskell中的高阶函数(或其他纯函数语言)能做什么,而C(函数指针和嵌套函数扩展)不能做什么?我从未使用过这个gcc扩展;但我会根据我对你给出的链接的解释来解释 就我对文档的理解而言,关键的区别在于,这些嵌套函数不允许您构建函数程序员在“闭包”下理解的内容——这些嵌套函数不能在其定义上下文之外使用,因为它们使用的堆栈变量在外部函数退出后丢失 在Haskell中,当我执行以下操作时: const x=\y->x foo=const 2——记住或

GCC具有允许使用嵌套函数的功能


实际上,我不明白Haskell中的高阶函数(或其他纯函数语言)能做什么,而C(函数指针和嵌套函数扩展)不能做什么?

我从未使用过这个gcc扩展;但我会根据我对你给出的链接的解释来解释

就我对文档的理解而言,关键的区别在于,这些嵌套函数不允许您构建函数程序员在“闭包”下理解的内容——这些嵌套函数不能在其定义上下文之外使用,因为它们使用的堆栈变量在外部函数退出后丢失

在Haskell中,当我执行以下操作时:

const x=\y->x
foo=const 2——记住或“结束”2
bar=foo1——现在,bar=2
您可以看到,当将
const
应用于
2
时,参数
2
被我们称为
foo
的闭包“保存”。之后,在
栏中可以调用并返回
2
,因为它仍然在
foo
中被记住。然而,在C中:

typedef int(*int_至int_fn)(int);
int_至int_fn常数(int x)
{
int常数_impl(int y){返回x;}
返回常数\u impl;
}
int main()
{
int_至int_fn foo=常数(2);
int bar=foo(1);
}
这甚至可能不会编译,但如果它会编译,它将违背我们对C函数的基本期望:
foo
中的
x
,由
常量
参数构成,需要保留在某个地方(可能不在堆栈上!),直到稍后调用
foo
。这不是东西的基本工作原理——从这个意义上说,C是基本的(我们可能需要在堆上分配一些东西,复制东西,稍后清理,担心引用/值等)


通过研究C++11 lambda语法,可能会获得一些启示。在那里,
constant\u impl
可以写在下面的某个地方:

auto constant_impl=[x](int y){return x;}

这里的
[x]
部分正是我们告诉编译器“请替我记住x!”的地方。

实际使用高阶函数的关键是需要闭包:一个普通的旧C函数,除了它的参数外,只能使用全局/静态数据。这意味着

GHCi>过滤器(>4)[7,4,3,6,87,5,4]
[7,6,87,5]

不能真正工作,除非你定义全局

bool largerThan4(int i) {return (i>4);}
这显然不符合比例。无法从程序中的其他地方“注入”数字4。函数式语言将此类信息打包在闭包中

现在,这个GNUC扩展为您提供了有限意义上的闭包,我认为这与:局部函数可以引用其包含范围内的变量的意义相同。这对,比如说

typedef std::vector<int> IntArray;

IntArray filter (const IntArray& a, std::function<bool(int)> pred) {
  IntArray result;
  for(auto& i: a) if (pred(i)) result.push_back(i);
  return result;
}

int main() {
  std::vector<int> v{{7,4,3,6,87,5,4}};
  int minNumber = 4;
  for(auto i: filter(v, [&](int i){return i>minNumber;}))
    cout << i << endl;
  return 0;
}
typedef std::vector IntArray;
IntArray过滤器(常量IntArray&a,标准::函数pred){
无阵列结果;
对于(auto&i:a)if(pred(i))结果,向后推(i);
返回结果;
}
int main(){
std::向量v{{7,4,3,6,87,5,4};
int minNumber=4;
for(自动i:filter(v,[&](int i){return i>minNumber;}))

cout高阶函数与嵌套函数定义几乎无关。您可以编写高阶函数,而无需此扩展;只需将函数指针作为参数或返回一个参数即可。是的,这些语言同样“强大”,haskell只需要做这些高阶函数,而不需要C所需的冗长。就像C可以处理状态而不需要haskell所需的冗长一样。@SteveCox正在替换的冗长
{
with
do
=
with
它编译,但根据:如果在包含函数退出后试图通过其地址调用嵌套函数,所有的麻烦都会随之消失。