{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreidd5d2tuhmuxgcagsc6oq5icphi3jw2p6wafkq3av53arkv3rz5oi",
"uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mgmiyqpvsdb2"
},
"path": "/t/synthesizing-runtimerep-indexed-type-class-instances-in-a-ghc-plugin-to-simulate-monomorphization/13774#post_2",
"publishedAt": "2026-03-09T08:58:49.000Z",
"site": "https://discourse.haskell.org",
"tags": [
"Levity polymorphism",
"@Double"
],
"textContent": "A good background paper is Levity polymorphism. Worth reading if you are digging into this.\n\nI can’t comment about compiler support until I understand the proposed solution, the one you attribute to Ed K. The problem is a fundamental one. If we have\n\n\n f :: Num a => a -> a\n f x = ...lots of code...\n\n\nNow if we want to apply `f` to an unboxed int, thus `(f @Double# 19882.234#)` we are stuck. The gobs of compiled matchine code for `f` manipulates boxed pointers, but we want compiled code that manipulates unboxed floats. Different machine instructions!\n\nThe only solutions I know are\n\n * Box the `Double#` before calling `f` – but that negates the whole point, which is to manipulate unboxed values exclusively.\n * Make a copy of the source code for `f`, specifically for `Double#`, and compile that. Now we have two versions of `f`. That’s fine but it’s hard to know which types to specialise `f` for (there are an infinite number of unboxed types). .NET does this, but GHC currently makes no attempt to do so.\n\n\n\nIt’d be worth having a clear design before thinking about implementation strategies.",
"title": "Synthesizing `RuntimeRep`-indexed type class instances in a GHC plugin to simulate monomorphization"
}