5

由于对我昨天发布的关于 Scala 元组的问题的一些有用答案,我一直在研究 Scala HLists。我想从那个问题重新散列一个 C++ 示例来问另一个问题:

在 C++ 中,可以实现使用模板特化终止的编译时递归。我经常在 boost 元组上执行此操作,就像 Scala/Haskell HLists 一样,它是通过多次组合通用“cons”类型来构造的,每个相关类型一次并以 null_type 终止。所以这:

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

在引擎盖下实现为:

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

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

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 上运行的 Scala 具有反射功能 - 因此大概可以使用运行时递归和使用清单和模式匹配的函数来实现。但我很想知道是否可以使用编译时递归来做类似于 C++ 示例的事情?

4

3 回答 3

4

是的,可以使用隐式参数实现编译时递归。看:

http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/
http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html

于 2011-03-22T08:12:14.117 回答
2

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

于 2012-06-13T08:04:29.367 回答
0

是的你可以。请参阅我的博客文章,了解如何在 Scala 的类型系统中实现SKI 演算,了解最一般的情况。我还写过关于循环展开和条件编译的更具体的案例。最后,这个小难题的解决方案展示了如何实现编译时递归的一种方式的本质。

于 2012-06-13T13:06:55.973 回答