Stream: advent of code

Topic: {unknown: _field}


view this post on Zulip Aurélien Geron (Dec 03 2025 at 06:53):

Hi!
I'm trying to do day 1 of AoC 2025. I'm getting a compiler error that I really don't understand:

-- TYPE MISMATCH ---------------------------------

This expression is used in an unexpected way:
   ┌─ day01.roc:10:19
   │
10 │             num = num_str.to_i32()?
   │                   ^^^^^^^

It has the type:
    Str

But I expected it to be:
    { unknown: _field }

Found 1 error(s) and 0 warning(s) for day01.roc.

Roc crashed: non-exhaustive match

Here's my program:

app [main!] { pf: platform "https://github.com/lukewilliamboswell/roc-platform-template-zig/releases/download/0.3/98T93wthPgoBRLYtPTT4RBBsQunrfDG94gihPf1zYYmE.tar.zst" }

import pf.Stdout

parse_instruction = |chars| {
    match chars {
        [] => Err(ParsingError)
        [c, ..rest] => {
            num_str = Str.from_utf8(rest)?
            num = num_str.to_i32()?
            if c == 'L' { Ok(-num) } else { Ok(num) }
        }
    }
}


main! = |_args| {
    res = parse_instruction("L12".to_utf8())
    match res {
        Ok(num) => {
            Stdout.line!(num.to_str())
            Ok({})
        }
        _ => Err(Exit(1))
    }
}

view this post on Zulip Anton (Dec 03 2025 at 10:12):

I'll take a look

view this post on Zulip Anton (Dec 03 2025 at 16:07):

I got sidetracked by adding missing tests, I'm almost done though

view this post on Zulip Anton (Dec 03 2025 at 18:36):

Instead of num_str.to_i32() it needs to be I32.from_str(num_str).

view this post on Zulip Anton (Dec 03 2025 at 18:37):

I will make an issue for the bad error message

view this post on Zulip Aurélien Geron (Dec 04 2025 at 23:59):

I've solved both parts of AoC 2025 Day 01 using the old compiler, then I ported the code as best I could to the new compiler, and roc check day01.roc says there are no errors, but I get a segfault at runtime. I tried to activate the ref counting logs as instructed by @Luke Boswell , but I'm not sure I did it correctly because I don't understand how I can use this output. Here's the full program:

app [main!] { pf: platform "https://github.com/lukewilliamboswell/roc-platform-template-zig/releases/download/0.3/98T93wthPgoBRLYtPTT4RBBsQunrfDG94gihPf1zYYmE.tar.zst" }

import pf.Stdout

data =
    \\L50
    \\L12
    \\R13
    \\L1
    \\L5
    \\R5


parse_instruction: List(U8) -> Try(I32, _)
parse_instruction = |chars| {
    match chars {
        [] => Err(ParsingError)
        [c, .. as rest] => {
            num_str = Str.from_utf8(rest)?
            num = I32.from_str(num_str)?
            if c == 'L' { Ok(-num) } else { Ok(num) }
        }
    }
}

count_zeroes_with_clicks: I32, I32 -> I32
count_zeroes_with_clicks = |pos, new_pos| {
    div_floor = |i| {
        if i < 0 { (i + 1) // 100 - 1 } else { i // 100 }
    }

    incr = (div_floor(new_pos) - div_floor(pos)).abs()
    if new_pos < pos {
        incr + (if new_pos % 100 == 0 { 1 } else { 0 }) - (if pos % 100 == 0 { 1 } else { 0 })
    } else {
        incr
    }
}

compute_password: List(I32), I32, I32, Bool -> I32
compute_password = |instructions, pos, count, with_clicks| {
    match instructions {
        [] => count
        [inst, .. as rest] => {
            new_pos = pos + inst
            new_count =
                count
                +
                if with_clicks {
                    count_zeroes_with_clicks(pos, new_pos)
                } else if new_pos % 100 == 0 {
                    1
                } else {
                    0
                }
            rest->compute_password(new_pos, new_count, with_clicks)
        }
    }
}

map_try: List(a), (a -> Try(b, c)) -> Try(List(b), c)
map_try = |list, to_result_fun| {
    list->walk_try(
        [],
        |state, elem| {
            match to_result_fun(elem) {
                Ok(ok) => Ok(state.append(ok))
                Err(b) => Err(b)
            }
        }
    )
}

walk_try: List(a), s, (s, a -> Try(s, c)) -> Try(s, c)
walk_try = |list, init, func| {
    match list {
        [] => { Ok(init) }
        [val, .. as rest] => {
            maybe_state = func(init, val)
            match maybe_state {
                Ok(state) => walk_try(rest, state, func)
                Err(b) => Err(b)
            }
        }
    }
}

main!: List(Str) => Try({  }, [Exit(I32)])
main! = |_args| {
    lines_utf8 = data.split_on("\n").map(|s| s.to_utf8())
    maybe_instructions = lines_utf8->map_try(parse_instruction)
    match maybe_instructions {
        Ok(instructions) => {
            result1 = instructions->compute_password(50, 0, False)
            Stdout.line!(result1.to_str())

            result2 = instructions->compute_password(50, 0, True)
            Stdout.line!(result2.to_str())

            Ok({})
        }
        _ => {
            Stdout.line!("Error")
            Err(Exit(1))
        }
    }
}

Here's the output:

debug: [HOST] Building args...
debug: [ALLOC] ptr=0x1034c0008 size=40 align=8
debug: [ALLOC] ptr=0x1034e0008 size=137 align=8
debug: [HOST] args_list ptr=0x1034c0018 len=1
debug: [HOST] Calling roc__main_for_host...
error: Child process /Users/ageron/Library/Caches/roc/5931167c7313ef73dbb36e68e48b39cf/temp/roc-tmp-ZtoLGEfLd8V5hXupRG23Usp7b6PNT2Iz/roc_run_994723065 killed by signal: 11
error: Child process crashed with segmentation fault (SIGSEGV)

Thanks for your help.


Last updated: Dec 21 2025 at 12:15 UTC