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