{
  "$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"
}