2011-03-19 76 views
5

由于我昨天发布了关于Scala中元组的问题的一些有用答案,我一直在寻找Scala HLists。我想重新散列一个C++的例子来问这个问题:Scala编译时递归?

在C++中,可以使用模板专门化实现编译时递归。我经常对boost元组进行操作,这些元组像Scala/Haskell HList一样,通过多次构造泛型'cons'来构造,每个相关类型一次,并以null_type结尾。因此,这:

boost::tuple<int, std::string, float> 

在引擎盖下实施:

cons<int, cons<std::string, cons<float, null_type> > > 

然后,我们可以写一个对函数在该结构上递归在编译时,终止时的第二,更专门函数匹配最终的缺点类型。一个简单的例子,数如下所示的元素个数:

template<typename T1, typename T2> 
void countTupleElements(boost::tuples::cons<T1, T2>& tupleRec, int index, const std::vector<std::string>& vals) 
{ 
    return 1 + countTupleElements(tupleRec.tail); 
} 

template<typename T> 
void countTupleElements(boost::tuples::cons<T, boost::tuples::null_type>& tupleRec, int index, const std::vector<std::string>& vals) 
{ 
    return 1; 
} 

最重要的是这种模式的情况下,经常使用,你想要做不同的每个不同的元组元素类型(在我的例子中未示出)的东西:在C++编译时,递归是非常重要的,因为一旦代码运行,类型信息就会因为所有有用的目的而丢失。

我的问题是,与Scala HList可能类似,例如,

val example = 1 :: 2.0 :: "Hello" :: "World" :: HNil 

我知道,斯卡拉,运行在JVM上,有反思 - 所以想必这可以使用运行时间递归使用清单和模式匹配功能来实现。但我有兴趣知道是否可以使用编译时递归来做类似于C++示例的事情?

+0

我不确定在这里问什么。但考虑到你的问题的总体趋势,我想知道你是否看过有关Scala类型系统中Church数字的博客?或Scala类型系统中的SKI演算? – 2011-03-20 23:27:53

+0

谢谢丹尼尔。你的各种建议被证明是非常有用的。我也一直在ScalaQuery来源中寻找灵感。 – 2011-03-21 11:20:22

+0

你可以添加一个更有趣的“你想为每个元组元素类型做不同的事情”的例子吗? – 2012-01-03 00:04:13

回答

2

还有就是在这本新书中的Scala深度由Joshua Suereth一个很好的例子。 7.4节是“使用类型系统进行条件执行”,它介绍了HList构造以及如何使用编译时递归来实现可以访问HList特定元素的IndexedView类型。这用于实现一个AtIndex类型,用于在编译时检索单个值。