I have trouble writing a simple dictionary encoder, would appreciate any help!
To avoid X Y problem: I am looking for the most straightforward way to work with dynamic JSON records, e.g. as a Dict Str a
. I cannot use JSON list of "pairs" instead etc.
What I came up with:
main.roc
app "simple-dictionary"
packages {
pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br"
}
imports [
pf.Stdout,
json.Json,
]
provides [main] to pf
Dictionary a := Dict Str a implements [
Encoding { toEncoder: toDictionaryEncoder },
Inspect, # auto derive
Eq, # auto derive
]
toDictionaryEncoder : Dictionary val -> Encoder fmt where val implements Encoding, fmt implements EncoderFormatting
toDictionaryEncoder = \@Dictionary val ->
bytes, fmt <- Encode.custom
Encode.appendWith
bytes
(fmt.record (
(key, value) <- Dict.toList val |> List.map
{
key,
value : Encode.toEncoder value
}
))
fmt
main = @Dictionary (Dict.single "a" 0) |> Inspect.toStr |> Stdout.line
roc check
error:
thread '<unnamed>' panicked at crates/compiler/solve/src/specialize.rs:866:25:
lambda set region not resolved: (`17.IdentId(2)`, MemberSpecializationInfo { _phase: PhantomData<roc_can::abilities::Resolved>, symbol: `17.IdentId(2)`, specialization_lambda_sets: VecMap { keys: [1], values: [144] } })
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Not at all sure it will help, but you could try putting a where
on Dictionary a
to specify that a has Encoding
.
Not sure what syntax are you referring to?
I think he meant a implements Decoding
(the original keyword was has
and we later changed it to implements
)
For
Dictionary a where a implements Encoding := Dict Str a implements [
Encoding { toEncoder: toDictionaryEncoder },
Inspect, # auto derive
Eq, # auto derive
]
I am getting
I was partway through parsing an ability definition, but I got stuck
here:
63│ Dictionary a where a implements Encoding := Dict Str a implements [
^
I was expecting to see a value signature next.
Should be:
Dictionary a := Dict Str a where a implements Encoding implements [...]
Got it. Yeah, this doesn't make a difference to the original error
One other thought but still a shot in the dark (don't have access to test rn). What happens if you type the number?
Try typing it in the final line Dict.single "a" 0u64
Did not help. I tried to minimize to the following:
test : fmt -> List U8 where fmt implements EncoderFormatting
test = \fmt -> Encode.appendWith
[]
(fmt.record [{key: "a", value: Encode.toEncoder ""}])
fmt
main = Stdout.line "Ok"
And now I am getting a more meaningful error
This expression is used in an unexpected way:
89│ (fmt.record [{key: "a", value: Encode.toEncoder ""}])
^^^^^^^^^^
This fmt value is a:
fmt where fmt implements EncoderFormatting
But you are trying to use it as:
{ record : * }b
Note: The type variable fmt says it can take on any value that
implements the ability EncoderFormatting.
But, I see that the type is only ever used as a a record value. Can
you replace fmt with a more specific type?
Am I calling the function of the ability wrong?
https://www.roc-lang.org/builtins/Encode#EncoderFormatting
I realized my mistake. The right question is half the answer :)
Being member of EncoderFormatting
, record
function is not a member of fmt
value, but is a function luckily exposed in the built-in Encode module. So the call should be Encode.record
, and the full implementation looks like
toDictionaryEncoder : Dictionary val -> Encoder fmt where val implements Encoding, fmt implements EncoderFormatting
toDictionaryEncoder = \@Dictionary val ->
bytes, fmt <- Encode.custom
Encode.appendWith
bytes
(Encode.record (
(key, value) <- Dict.toList val |> List.map
{
key,
value : Encode.toEncoder value
}
))
fmt
Karakatiza has marked this topic as resolved.
The error message
This expression is used in an unexpected way:
89│ (fmt.record [{key: "a", value: Encode.toEncoder ""}])
^^^^^^^^^^
This fmt value is a:
fmt where fmt implements EncoderFormatting
But you are trying to use it as:
{ record : * }b
was much more useful than the original compiler panic message
Last updated: Jul 06 2025 at 12:14 UTC