VinylRecords/Vinyl — pull request #28 by conklech (2013-12-04 23:14:29+00:00)
Title: Implement RULES-based unrolling of record lenses

We can fully (?) unroll record lenses at compile time using RULES and a technique identified by Roman Leshchinskiy for [Tricking GHC into evaluating recursive functions at compile time](http://unlines.wordpress.com/2009/11/05/tricking-ghc-into-evaluating-recursive-functions-at-compile-time/). @ekmett described the trick as "sneaky," but it seems to work well.

With this, GHC produces very clean Core with `-O2`, at least in the cases I've examined. For instance, `rGet someField :: PlainRec rs -> t`, when `rs` is known at compile time, leads to Core that is *simpler* than hand-coded pattern-matching. (As of GHC 7.6--maybe if somebody figures out [this GHC bug](https://ghc.haskell.org/trac/ghc/ticket/4139) and related matters, that will change?)

See a sample module, with pre- and post-patch Core, at https://gist.github.com/conklech/7796570. I have not benchmarked this implementation; it may lead to regressions in situations I haven't considered.

The main downside is an otherwise-redundant unit component in one of the constructors of `Elem`. See Roman's post for an explanation of why it's needed.

The same technique could possibly be applied elsewhere, for instance with `cast`.