【发布时间】:2010-12-10 16:53:21
【问题描述】:
是否可以使用 C++(或 C#)模板来模拟 Haskell 的类型类功能?
这样做是否有意义或有任何回报?
我试图在 C++ 中创建一个 Functor 类,但我做不到。我试过这样的事情:
#include <iostream>
using namespace std;
//A function class to make types more readable
template <class input, class output> class Function {
private:
output (*ptrfunc )(input);
public:
Function(output (* ptr)(input)) {
ptrfunc = ptr;
}
output call(input x) {return (*ptrfunc)(x);}
output operator() (input x) { return call(x);}
};
//the functor "typeclass"
template <class a> class Functor{
public:
template <class b> Functor<b> fmap(Function<a,b> func);
};
// an container type to be declared "instance" of functor:
template <class a> class List : public Functor<a> {
private:
a * ptrList;
int size;
public:
List(int n) { //constructor;
ptrList = new a[n];
size = n;
}
List(List<a> const& other) { //copy constructor
size = other.size;
ptrList = new a[size];
for(int i = 0; i<size; i++)
(*this)[i] = other[i];
}
~List() { delete ptrList;} //destructor
a& operator[](int i) { return ptrList[i];} // subscript operator just for easy notation
const a& operator[](int i) const { return ptrList[i];}// subscript operator just for easy notation
template <class b> List<b> fmap(Function<a,b> func) { //"instance" version of fmap
List<b> temp(size);
for(int i = 0; i < size; i++)
temp[i] = func((*this)[i]);
return temp;
}
};
int test(int k) { return 2 * k;}
int main(void) {
Function<int, int> func(&test);
List<int> lista(10);
for(int i = 0; i < 10; i++)
lista[i] = i;
List<int> lista2(lista.fmap(func));
for(int i = 0; i < 10; i++)
cout << lista2[i] << " ";
cout << endl;
return 0;
}
它做了它应该做的事情,但是在 C++ 中使用这种模式是否有意义?真的和haskell中的模式一样吗:
data List a = -- some stuff
class Functor f where
fmap :: (a -> b) -> f a -> f b
instance (Functor List) where
-- some stuff
对我来说似乎不是一回事,因为Functor f、f 是一种 * -> * 类型的构造函数,而在我上面的定义中 Functor<a>、a 不是模板a<something>,但“包含”数据类型本身。
有办法解决吗?更重要的是:尝试将这种模式复制到 C++ 是否有意义?在我看来,C# 比 C++ 更类似于函数式编程风格。有没有办法在 C# 中做到这一点?
【问题讨论】:
-
一个好的经验法则是“不,假装用你正在使用的其他语言编程是不值得的”。如果您想编写 Haskell 代码,请为 Haskell 编译器编写它。只要你在写 C++ 代码,你最好写惯用的 C++
-
也许osl.iu.edu/~kyross/pub/20040929-type-class-slides.pdf 或citeseerx.ist.psu.edu/viewdoc/… 会有所帮助。但是,在您的
Functor情况下,基类绝对没有意义(因为不能将fmap声明为virtual)。 -
但是是的,您可以使用模板编写通用仿函数。虽然这样做的风格会与 Haskal 中的略有不同。
-
我只想指出,您可能会将 C++ 程序员与 Functor 一词混淆,因为该术语在 C++ 中被滥用为表示功能对象(在某种意义上是一种特定类型的 Functor)。在 haskell 中,Functor 表示分类 Functor 而不是 C++ Functor(功能对象)。
-
您可能还想阅读 C++ 概念与提升 BCCL:stackoverflow.com/questions/1352571/…。这不是一个详尽的答案,但我相信它有助于澄清删除 C++0x 概念的问题。
标签: c# c++ design-patterns haskell typeclass