Scala compile-time recursion?
As a result of some helpful answers to a question I posted yesterday about tuples in Scala, I've been looking at Scala HLists. I'd like to re-hash a C++ example from that question 开发者_如何学运维to ask another:
In C++ one can implement compile-time recursion terminated using template specialization. I've often done this operating on boost tuples which, like Scala/Haskell HLists are constructed by composing the generic 'cons' type multiple times, once for each relevant type and terminating with null_type. So this:
boost::tuple<int, std::string, float>
is implemented under the hood as:
cons<int, cons<std::string, cons<float, null_type> > >
We can then write a pair of functions that recurse at compile-time over this structure, terminating when the second, more-specialized function matches the final cons type. A simple example, counting the number of elements is shown below:
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;
}
Crucially this pattern is often used in circumstances where you want to do something different for each of the various tuple element types (not illustrated in my example): in C++ compile-time recursion is essential as once code is running, the type information is lost for all useful purposes.
My question is, is something similar possible with a Scala HList, e.g.
val example = 1 :: 2.0 :: "Hello" :: "World" :: HNil
I'm aware that Scala, running on the JVM, has reflection - and so presumably this could be implemented using run-time recursion with a function using manifests and pattern matching. But I'm interested in knowing if it's possible to do something similar to the C++ example, using compile-time recursion?
Yes, it's possible to implement compile time recursion using implicit parameters. See:
http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/
http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html
There is an excellent example of this in the new book Scala in Depth by Joshua Suereth. Section 7.4 is "Conditional execution using the type system" and it introduces the HList construct and how you can use compile time recursion to implement an IndexedView type that can access a specific element of the HList. This is used to implement an AtIndex type which is used to retrieve individual values at compile time.
Yes you can. See my blog post about how to implement the SKI calculus in Scala's type system for the most general case. I have also written about the more specific case of loop unrolling and conditional compilation. Finally the solution to this little puzzle shows the essence of one way how compile time recursion can be implemented.
精彩评论