Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个自应用阶乘函数的类型是什么? < >我在C++中编写了匿名阶乘函数,并用g+4.4.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; } struct aaaa // Not its real name. { template<typename a, typename b> auto operator()(a self, b n) const { } };_C++_Haskell_Types_C++14_Generic Lambda - Fatal编程技术网

这个自应用阶乘函数的类型是什么? < >我在C++中编写了匿名阶乘函数,并用g+4.4.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; } struct aaaa // Not its real name. { template<typename a, typename b> auto operator()(a self, b n) const { } };

这个自应用阶乘函数的类型是什么? < >我在C++中编写了匿名阶乘函数,并用g+4.4.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; } struct aaaa // Not its real name. { template<typename a, typename b> auto operator()(a self, b n) const { } };,c++,haskell,types,c++14,generic-lambda,C++,Haskell,Types,C++14,Generic Lambda,我必须定义一些递归类型来解决它: 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函数是什么类型?下面的表达式auto fac=是一个lambda表达式,编译器会自动从中生成一个闭包对象

我必须定义一些递归类型来解决它:

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
函数是什么类型?

下面的表达式
auto fac=
是一个lambda表达式,编译器会自动从中生成一个闭包对象。该对象的类型是唯一的,并且只有编译器知道

从N4296开始,§5.1.2/3[expr.prim.lambda]

lambda表达式的类型(也是闭包对象的类型)是唯一的、未命名的非联合类类型,称为闭包类型,其属性如下所述。该类类型既不是聚合类型(8.5.1),也不是文本类型(3.9)。闭包类型在包含相应lambda表达式的最小块作用域、类作用域或命名空间作用域中声明

请注意,因此,即使是两个相同的lambda表达式也将具有不同的类型。比如说,

auto l1 = []{};
auto l2 = []{}; // l1 and l2 are of different types

您的lambda表达式是一个C++14通用lambda,编译器将其转换为类似于以下内容的类:

struct __unique_name
{
    template<typename Arg1, typename Arg2>
    auto operator()(Arg1 self, Arg2 n) const
    { 
        // body of your lambda
    }
};
struct\uuu唯一\u名称
{
模板
自动运算符()(Arg1 self,Arg2 n)常量
{ 
//你的lambda的尸体
}
};

我无法评论Haskell部分,但是递归表达式在C++中工作的原因是因为在每个调用中只传递了一个关闭对象实例(<代码> FA< <代码> >)。“代码>操作程序()/<代码>是一个模板,它可以推断lambda的类型,即使它不是一个你可以命名的。

< p> C++ >代码> FAC < /C> >实际上不是一个函数,而是一个具有成员函数的结构。
#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;
}
struct aaaa // Not its real name.
{
    template<typename a, typename b>
    auto operator()(a self, b n) const
    { 
    }
};
因此,函数的参数不是函数本身,而是将其作为成员的对象。
这样做的一个效果是函数的类型(即
运算符()
的类型)不会出现在
运算符()
函数本身的类型中。
(self的类型是定义函数的结构。)

模板部分不是此工作所必需的;这是
fac
功能的非通用版本:

如果我们保留模板并将
operator()
重命名为
applY

// The Y type
template<typename a>
struct Y
{
    // The wrapped function has type (Y<a>, a) -> a
    a applY(const Y<a>& self, a n) const
    { 
        if(n < 1)
            return 1;
        else 
            return n * self.applY(self, n-1);
    }
};

template<typename a>
a fac(a n)
{
    Y<a> y;
    return y.applY(y, n);
}
self
是一个函数,
fac2
的类型必须是

X -> Int -> Int
对于某些
X

由于
self
是一个函数,
self$n-1
是一个Int,因此
self
的类型也是
X->Int->Int

但是
X
会是什么呢?
它必须与
self
本身的类型相同,即
X->Int->Int

但这意味着
self
的类型是(代替
X
):

因此类型
X
也必须是

(X -> Int -> Int) -> Int -> Int  
因此,
self
的类型必须是

((X -> Int -> Int) -> Int -> Int) -> Int -> Int
以此类推,无限期。
也就是说,在Haskell中,类型是无限的


<> P. > Haskell的解决方案本质上明确地介绍了C++通过其成员结构生成的必要间接性。

,正如其他人指出的,lambda充当一个涉及模板的结构。然后问题变成:为什么Haskell不能输入自应用程序,而C++可以?

#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;
}
struct aaaa // Not its real name.
{
    template<typename a, typename b>
    auto operator()(a self, b n) const
    { 
    }
};
答案在于C++模板与Haskell多态函数的区别。比较这些:

-- valid Haskell
foo :: forall a b. a -> b -> a
foo x y = x

// valid C++
template <typename a, typename b>
a foo(a x, b y) { return x; }
Haskell定义不会进行类型检查:当
x
为任意类型时,不能保证可以执行
x+1
。相反,C++代码很好。
a
的某些替换导致不正确的代码,这一事实目前并不重要


推迟此检查会导致允许一些“无限类型的值”。Python或Scheme等动态语言进一步将这些类型错误推迟到运行时,当然可以很好地处理自应用程序。

当您将
auto
替换为某些类型时,例如
int
编译器应该告诉您它无法推断类型并给出它们的名称。但是我还没有测试它,但是为什么g++能推断出我的fac函数的正确类型呢?作为补充,编写Haskell版本的更好方法是将它分为递归位(即,一般来说,
fix::(a->a)->a
fix f=f(fix f)
)和非递归位。非递归位是
fact1 recur n=如果n==0,那么1 else n*recur(n-1)
,您会注意到这(a)不是递归的,(b)有一个有限且可推断的类型
fact1::(Int->Int)->(Int->Int)
,并且(c)实现一个阶乘的“步骤”。然后我们通过组合递归和非递归位来“完成”它:
fact=fix-fact1
。好吧,我不会把
fix
称为Y组合器。它具有相同的效果,但是有许多固定点组合,其中
Y
fix
只是两个例子。哦,是的,我现在记得了:
Data.Function
中的定义使
fix(1:)
成为一个循环链表,而不是无限链表,对于其他类似的东西也是如此。它可以让您将数据结构捆绑在一起,而更明显的
fixf=f(fixf)
则不能。
-- valid Haskell
foo :: forall a b. a -> b -> a
foo x y = x

// valid C++
template <typename a, typename b>
a foo(a x, b y) { return x; }
-- INVALID Haskell
foo :: forall a b. a -> b -> a
foo x y = x+1

// valid C++
template <typename a, typename b>
a foo(a x, b y) { return x+1; }