我在C++中编写了一个匿名的阶乘函数,并使用g++4.9.2编译了我的代码。它能够正常工作,但是我不知道我的函数的类型。
#include<iostream>
#include<functional>
using std::function;
int main()
{
//tested at g++ 4.9.2
//g++ -std=c++1y -o anony anony.cpp
auto fac = [](auto self,auto n)->auto{
if(n < 1)
return 1;
else
return n * self(self,n-1);
};
std::cout<<fac(fac,3)<<std::endl;//6
return 0;
}
因此,我想知道:fac
和self
的类型是什么?
如果我只是将C++代码翻译成Haskell,它不会编译,因为
它涉及到无限类型:
fac2 self 0 = 1
fac2 self n = n * (self self $ n-1)
我必须定义一些递归类型并解决它:
data Y a = Y ((Y a)->a->a)
fac2 self 0 = 1
fac2 self n = n * ((applY self self) (n-1))
where applY (Y f1) f2 = f1 f2
fact2 = fac2 $ Y fac2
那么,为什么g++可以获得与
fac
函数完全匹配的类型,而g++认为fac
函数的类型是什么?
fac
是通用lambda,它像一个带有模板化operator()
的函数对象。请注意,这些是C++14中新增的。 - user657267fix :: (a -> a) -> a
与fix f = f(fix f)
)和非递归部分。非递归部分是fact1 recur n = if n == 0 then 1 else n * recur (n-1)
,你会注意到这个函数(a)不是递归的,(b)有一个有限且可推断的类型fact1 :: (Int -> Int) -> (Int -> Int)
,(c)实现了阶乘的单个“步骤”。然后我们只需通过组合递归和非递归部分来“完成”它:fact = fix fact1
。 - J. AbrahamsonY
类型写成一个newtype
而不是data
,这会导致更高效的运行时表示。 - dfeuerData.Function
中的定义使fix (1:)
成为一个循环链表,而不是无限列表,类似于其他一些东西。它可以让你把数据结构打成结,而更明显的fix f = f (fix f)
则不行。 - dfeuer