In Matthew Pickering's blog post about inlining, he mentions a trick to force GHC to inline recursive definitions applied to a statically known argument:
However, there is a trick that can be used in order to tell GHC that an argument is truly static. We replace the value argument with a type argument. Then by defining suitable type class instances, we can recurse on the structure of the type as we would on a normal value. This time however, GHC will happily inline each “recursive” call as each call to sum is at a different type.
Then the blog post proceeds to show a very simplistic example using type-level Nats. My question is about forcing GHC to fully inline functions over actually interesting types.
In my case, I have a computation that is via a monadic DSL. Under the hood, the DSL is an RWS. Looking at the generated Core with lots of INLINE pragmas, I can see calls to the recursive functions that implement <> for the writer output. Since these functions are recursive, GHC doesn't inline them. But if it did, since the full RWS computation is static enough that the spine of the writer output could be fully unrolled during compilation, it would, after finitely many steps, arrive at Core with no recursive definitions left.
Taking the idea from Matt's blog post, we would need to have a type-level representation of the monadic value; I'd love to see a version of this (especially with good ergonomics!), but I am not too optimistic: unlike the Servant approach, we would need a way to bind variables to results (a la monadic >>=). Alternatively, are there any other mechanisms to tell GHC that its input size is statically known, so it shouldn't shy away from aggressively inlining recrusive definitions? For example, is it possible to emulate Agda-style sized types by using a graded monad with some appropriate size measure in the index?
P.s.: My aim is not mere optimization, but working around a Clash bug, so this elimination of recursive definitions by aggressive inlining would need to be something dependable, not a nice-to-have performance improvement.