Am I the only one who frequently gets confused by the error messages produced by the compiler when Result
s are involved? Seems like the mismatched use of Result
and Ok
/Err
contributes to the confusion. But I've pretty much never seen an error message involving a Result
that wasn't difficult to decipher. For example the below:
This when expression produces:
Result [
Err [InvalidTimeFormat],
Ok Time.Time,
] […]
But the type annotation on parseFractionalTime says it should be:
Result {
hour : Int Unsigned8,
minute : Int Unsigned8,
nanosecond : Int Unsigned32,
second : Int Unsigned8,
} […]
This makes no sense to me. The type annotation for parseFractionalTime is:
parseFractionalTime : List U8, List U8 -> Result Time [InvalidTimeFormat]
So what is the difference between:
Result [
Err [InvalidTimeFormat],
Ok Time.Time,
] […]
and
Result Time [InvalidTimeFormat]
I see the error message shows a Result [Ok .., Result .. ] as the unexpected return, where as the expected return is a Result {..} where {..} matches the type signature for my Date.Date type. What is this error message telling me?
So
{
hour : Int Unsigned8,
minute : Int Unsigned8,
nanosecond : Int Unsigned32,
second : Int Unsigned8,
}
Looks to just be an accidental inlining of Time.Time
So the error is that you have a:
Result [
Err [InvalidTimeFormat],
Ok Time.Time,
] […]
Which rewritten would be a:
Result (Result Time.Time [InvalidTimeFormat]) […]
In other words, you have nested results
Aside:
Results probably have poor errors cause they are just tags and not some sort of unique type. As such, they are actually really flexible cause they can be used as any generic tag.
Any errors specific to result would need to be careful cause someone technically could make valid tags in many case.
For example, this is valid (so we have our work cut out to make error nice while also dealing with that):
MyResult ok err : [OK ok, Err err]
x = OK 27
when x is
OK v -> v
Err _ -> crash "..."
Okay, I thought it looked like it was telling me I had a nested result. But I'm tearing my hair out trying to figure out where I could be nesting results, without success. :expressionless:
Can you share the code?
Sure! One moment...
parseFractionalTime : List U8, List U8 -> Result Time [InvalidTimeFormat]
parseFractionalTime = \wholeBytes, fractionalBytes ->
combineDurationResAndTime = \durationRes, time ->
when durationRes is
Ok duration -> Duration.addTimeAndDuration time duration |> Ok
Err _ -> Err InvalidTimeFormat
when (wholeBytes, utf8ToFrac fractionalBytes) is
([_,_], Ok frac) -> # hh
time <- parseLocalTimeHour wholeBytes |> Result.map
frac * nanosPerHour |> Num.round |> Duration.fromNanoseconds |> combineDurationResAndTime time
([_,_,_,_], Ok frac) -> # hhmm
time <- parseLocalTimeMinuteBasic wholeBytes |> Result.map
frac * nanosPerMinute |> Num.round |> Duration.fromNanoseconds |> combineDurationResAndTime time
([_,_,':',_,_], Ok frac) -> # hh:mm
time <- parseLocalTimeMinuteExtended wholeBytes |> Result.map
frac * nanosPerMinute |> Num.round |> Duration.fromNanoseconds |> combineDurationResAndTime time
([_,_,_,_,_,_], Ok frac) -> # hhmmss
time <- parseLocalTimeBasic wholeBytes |> Result.map
frac * nanosPerSecond |> Num.round |> Duration.fromNanoseconds |> combineDurationResAndTime time
([_,_,':',_,_,':',_,_], Ok frac) -> # hh:mm:ss
time <- parseLocalTimeExtended wholeBytes |> Result.map
frac * nanosPerSecond |> Num.round |> Duration.fromNanoseconds |> combineDurationResAndTime time
_ -> Err InvalidTimeFormat
and the external call here that returns the final value, Duration.addTimeAndDuration
:
addTimeAndDuration : Time, Duration -> Time
addTimeAndDuration = \time, duration ->
t1nanos = toNanoseconds duration
dNanos = Time.toNanosSinceMidnight time |> Num.toI128
t2Nanos = (dNanos + t1nanos) % Const.nanosPerDay
Time.fromNanosSinceMidnight t2Nanos
Result.map
to Result.try
?
Cause Result.map
Just maps the success case. So you are mapping the success case to a Result Time.Time [InvalidTimeFormat]
Ahhh... that would make sense..
Of course 🤦🏻♂️
I do feel like Result error messages tend to be pretty confusing. They often mismatch, like you say, since they are just a Tag union, so there is intermingled use of Result and Ok Err, combined with mismatched inlining of other types can get pretty messy.
Yeah, lots of room for improvement.
Ian McLerran has marked this topic as resolved.
Last updated: Jul 06 2025 at 12:14 UTC