For quite a long time already, Scala is Turing-complete at compile-time thanks to its advanced type system. Declarative language of implicits allows one to encode type-level computations in an elegant, functional manner. A number of programming techniques stem from this root, making it possible to state amazingly precise facts about programs.
Macros, introduced in the recent 2.10 release of Scala, also provide ways of doing things during compilation. With macros it is possible to write Scala functions that verify behaviors and enforce constraints at compile-time - something that has been traditionally done with types. Macros typically work in a straightforward, imperative way, being effective, but too bruteforce for some.
Are macros principled enough, or they are just a hack? Should one use macros when there are already such well-established libraries as Shapeless? In this talk, we will compare type-level and macro-based approaches to compile-time computations, discuss their areas of applicability and figure out how they can work together for mutual benefit.