I’m interested in starting work on porting roc-pg to the new compiler, if that would be helpful.
A few questions:
Does the following strategy sound reasonable?
A. Make the minimum necessary changes to get it working.
B. Evaluate whether any structural changes make sense given changes to Roc.
Any other questions I should be asking? :sweat_smile:
For example, have package imports been implemented yet?
Package imports have been implemented.
Im finding things every now and then porting packages accross, but Im making GH issues and theyre getting resolved pretty fast. No known issues.
You can probably use the basic-webserver or basic-cli built from source off the migration PR branch ... there definitely some rough edges but the http stuff looks to be working ok.
I figured worst case I could just add TCP to my TigerBeetle platform. I’ll give basic-webserver a shot first though.
I recall seeing some kind of discussion on this topic before, but I'm not sure where the thread is.
In roc-pg there are some modules that are nested in directories. For example, Bytes.Decode, which is a Decode.roc file in a Bytes directory. These were previously imported as e.g. Bytes.Decode, which no longer works in current Roc.
In this case, There is decoding happening outside of the Bytes.Decode module, and Bytes.Decode just deals with decoding primitive types from lists of bytes, along with a few helpers. It seems the author's original intent here was to use the Bytes namespace to signal that this module doesn't handle all decoding, just the decoding primitives.
The cleanest thing I've found is to just move Decode.roc and Encode.roc up a level, and import them as Decode, Encode. Consumer modules are bringing lots of values into scope using exposing, so nesting these types under a Bytes type makes that a lot more clumsy:
import Bytes exposing [Decode]
i8 = Decode.i8
i16 = Decode.i16
# etc.
Another option I considered was using a name like DecodeBytes, though that makes the type name longer too.
I'm looking for suggestions on how best to organize modules here given Roc's current design. If I'm changing the organization from what it originally was, I want to make sure I'm thoughtful about it. :slight_smile:
Also, “It’s not a big deal, don’t worry about it too much” is an answer I will totally accept! I just don’t want to casually undo thoughtful choices Agus made if I’m going to submit a PR :sweat_smile:
I believe the way to handle this now is to put them all into 1 module like:
# in Bytes.roc
Bytes := X.{
# all top level byte fns
Decode := Y.{
# all decode-specific functions
}
}
Then the user just imports Bytes and can do Bytes.Decode.i8 etc
you could also define in a diff module like:
# Bytes.Internal.Decode
Decode := Y.{ ... }
then import & export it as an alias:
# in Bytes.roc
import Bytes.Internal.Decode as D
Bytes := X.{
Decode :: D.Decode
}
Jared Ramirez said:
I believe the way to handle this now is to put them all into 1 module like:
# in Bytes.roc Bytes := X.{ # all top level byte fns Decode := Y.{ # all decode-specific functions } }
My instinct was to do exactly this, but then I realized that I'd need to update references to Bytes.Decode.i8 to be qualified, or do the clumsy assignment thing I mentioned above (which feels like something the language doesn't want me to do :sweat_smile:)
So instead of this:
import Decode exposing [await, map, u8, i32]
ProtocolBackend := [].{
header : Decode({ msg_type : U8, len : I32 }, _)
header = await(u8, |msg_type| map(i32, |len| { msg_type, len: len - 4 }))
}
I'd end up with this:
import Bytes exposing [Decode]
ProtocolBackend := [].{
header : Decode({ msg_type : U8, len : I32 }, _)
header = Decode.await(Decode.u8, |msg_type| Decode.map(Decode.i32, |len| { msg_type, len: len - 4 }))
}
I don't mind using the values fully qualified. I like the added clarity actually. Is this what would be considered idiomatic here?
Well, I was hoping to do the conversion without too many structural changes initially, but I see I have optional record fields to deal with too so I might just need to embrace the refactoring :sweat_smile:
What you ended up with is idiomatic! I personally like things quantified tho
But if you really wanted to match the original style, you could have one line importing/exposing Bytes then another line importing/exposing Bytes.Decode
I think this is very close. Everything is type checking, but when I attempt to build or run using the latest main for basic-cli, it hangs on the specialization step.
I also have some remaining questions about API given the changes to the module system and addition of static dispatch, but I'll get it working first!
Cool! I'm excited for this!
Perhaps this unblocks you temporarily? https://github.com/niclas-ahden/basic-cli/releases/tag/0.22.1
Hmm, I could actually give that a shot. I need to update my bitshifts anyway since they just changed.
Yeah, and tomorrow's basic-cli will probably be back to working. I'll maintain my fork as necessary, but it's not a replacement for the real thing :)
I'm just waiting for https://github.com/roc-lang/roc/pull/10312 to land (which unblocks Glue for the platforms) -- and then I plan to manually trigger a fresh nightly
Then work on basic-cli is unblocked and I can continue merging in PR's etc
I hadn't realised the current RC doesn't work with the nightly... so I'll trigger a fresh RC too. There has been quite a few changes land in basic-cli already since the last RC
Yeah so I don't think the problem is the platform at all. still hanging on specialization
roc check is < 200 ms tho
If you can wrap it up in a bow (minimal repro) and post a GH Issue that will be most helpful. I've been finding issues like this for a while and Richard fixes them pretty quickly (often faster than it took me to find and isolate the bug report :sweat_smile: ).
Then it usually just takes a few days for the fixes to flow through CI into a nightly etc
Yeah last time I encountered this he (or Jared) had it fixed in a flash! Might take me a bit to get a repro though, I'm not sure where to start :sweat_smile:
Maybe I can throw some tokens at it
Non blocking, as I can actually reorder definitions to make the issue go away.
And it works!
![]()
basic-webserver should be usable if you build from source
https://github.com/roc-lang/basic-webserver/pull/163
Last updated: Jul 23 2026 at 13:15 UTC