{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiddswksbj6zymwpp7wlny7p7fjrtj5l5dassp6lmab473kbzfnffi",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mnfmmu52mcg2"
  },
  "path": "/t/h2jvm-a-haskell-library-for-writing-jvm-bytecode/14182#post_3",
  "publishedAt": "2026-06-03T17:04:00.000Z",
  "site": "https://discourse.haskell.org",
  "tags": [
    "DList"
  ],
  "textContent": "Looks good and plainly written, I’ll bookmark it for next time I do something with the JVM\n\nBrowsed around and reviewed a little, have a few random suggestions\n\n* * *\n\nYou can avoid the possibility of an `UnmarkedLabel` error using a `MonadFix` instance and `rec` or `mdo`\n\n\n    emitNewLabel = do\n      label <- newLabel\n      emit $ JVM.Label label\n      pure label\n\n\n\n    mdo\n      emit $ JVM.IfICmp (IfGt trueLabel)\n      emit JVM.IConst0\n      emit $ Goto endLabel\n      emit JVM.IConst1\n      trueLabel <- emitNewLabel\n      emit JVM.IConst1\n      endLabel <- emitNewLabel\n      pure ()\n\n\nI’d rather use `rec` to spell out the scope, but this case is better with `mdo` because the labels are used throughout\n\n* * *\n\nIn `CodeState` instead of storing a list in reverse order you can use a `DList Instruction`\n\nCode that uses `IfCond` is repetitive because it’s denormalised\n\n\n    data IfCond label = IfEq label | IfNe label | IfLt label | IfGe label | IfGt label | IfLe label\n\n\nInstead you can factor:\n\n1 _x_ +1 _x_ +1 _x_ +1 _x_ +1 _x_ +1 _x_\n= (1+1+1+1+1+1)_x_\n= 6 _x_\n\n\n    data If label = If Cond label\n    data Cond = Eq | Ne | Lt | Ge | Gt | Le\n\n\nCan also keep the current patterns with synonyms like `pattern IfEq label = If Eq label` and a `{-# COMPLETE #-}` pragma\n\n* * *\n\nIn clauses of `Pretty` instances like this\n\n\n    pretty (InvokeSpecial c n d) =\n      \"invokespecial\" <+> pretty c <> \".\" <> pretty n <> pretty d\n\n\nI like to use `ViewPatterns` (or a synonym) so the shape of the output is less cluttered by calls to `pretty`, and it’s only called once if used more than once\n\n\n    pretty (InvokeSpecial (pretty -> c) (pretty -> n) (pretty -> d)) =\n      \"invokespecial\" <+> c <> \".\" <> n <> d\n\n\nI dunno how “pretty” you actually want for the pretty-printing to be, but I find that `Pretty` instances in general tend to overuse the explicit non-breaking horizontal (`hcat`, `hsep`, `<>`, `<+>`) and vertical (`vcat`, `vsep`) layouts without enough `group`ing, and should rather use the grouped combinators that allow breaks between all (`cat`, `sep`, `surround softline'`, `surround softline`) or between any (`fillCat`, `fillSep`)",
  "title": "H2JVM - A Haskell Library for writing JVM Bytecode"
}