Anyone planning to do Advent of Code 2021 in Roc? :smiley:
How much setup would it need? Is it for example possible to set up an AoC example?
I think it's a great opportunity to try out Roc, I'm just not sure how much time I'll have for AoC. So if there is expected overhead, I might reconsider Roc.
I think I'll give it a go. I've never done it and might as well do it in roc
Is it for example possible to set up an AoC example?
definitely! We could make an examples/advent-of-code
which has sort of a starter kit example for doing things like:
maybe just cli is enough?
it has writing/reading to terminal but idk about file IO
482952-59f1582e
I made a private leaderboard ^
Generally you don't need terminal, just file io/copying data into an array. They tend to give you a sample problem with a small input to interpret then either a larger input or many inputs in a file.
When I did it in Elm one year, I just copied the input data into a file called input.elm
and made it a String
or a List Int
. I figured my program didn't need to parse _any_ input, just that specific input. :smiling_devil:
But Elm has the excuse of being a front end language!
lmao
Brendan Hansknecht said:
Generally you don't need terminal, just file io/copying data into an array. They tend to give you a sample problem with a small input to interpret then either a larger input or many inputs in a file.
what about outputting an answer?
oh...fair...though could just write to file.
oh true lol
I thought I'd have a look at the previous AoC to see how to set it up. It's pretty easy to go inside example/cli
and just do something like cat input.txt | cargo run Day1.roc > output.txt
.
But I immediately needed to parse the input into a list of numbers and that's where I'm already lost. I know it's marked as a high priority built-in in https://github.com/rtfeldman/roc/issues/664, but unfortunately I currently don't have time to figure out how to implement it.
So based on this, I think I might do AoC (if at all) in a more familiar language, but I'm definitely interested in doing it again in Roc, as soon as the avant-garde has cleared the way. ;)
Hi Johannes, I solved last year's AoC with a very early version of Roc. You can read a little bit about it here: https://github.com/pithub/aoc2020/blob/master/WrapUp.md. My platform read files as a list of bytes, which were then parsed into a list of numbers, for example.
Thanks, @Pit Capitain! Looks really interesting! If I find some time, I might take inspiration from your repo. :+1:
I got most of the tutorial done: https://github.com/rtfeldman/roc/blob/trunk/TUTORIAL.md
I'll keep filling in missing sections over the next week, but hopefully what's there will be helpful so far!
Very nice :+1: It's really hard for me to resist, but I have other tasks I need to accomplish first :disappointed:
if anyone just joined for Advent of Code, welcome! :wave:
feel free to introduce yourself in #beginners > introductions and ask any Advent of Code related questions right here in this topic!
482952-59f1582e
dropping the private leaderboard I made for roc folks again ^
Hello! Trying Roc on 2021/01, starting out from examples/cli. Is there some working implemented str->num function? I tried out Str.toNum and Str.toU8 that I saw mentioned in the compiler/builtins/docs/*.roc but no luck so far
Martin Janiczek said:
Hello! Trying Roc on 2021/01, starting out from examples/cli. Is there some working implemented str->num function? I tried out Str.toNum and Str.toU8 that I saw mentioned in the compiler/builtins/docs/*.roc but no luck so far
We mentioned that in #beginners > tutorial and the change is coming: https://github.com/rtfeldman/roc/pull/2108
for day 1, if we save the inputs into a file, we need a way to read from that file. The tutorial mentions that in https://github.com/rtfeldman/roc/blob/trunk/TUTORIAL.md#tasks but does not show the implementation. WIP I guess.
I could not find any examples reading from a file. And you?
I don't know if it's the good channel to get help.
With the following code:
measurements = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263 ]
increases = List.walk measurements { counts: 0, previousElement: 600 } \state, elem ->
when state.previousElement is
Num previousElement if previousElement < elem -> { counts: state.counts + 1, previousElement: elem }
_ -> { state & previousElement: elem }
increases
(previousElement: 600 is not here to stay, only to experiment)
I got the following error:
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
The 2nd branch of this when does not match all the previous branches:
6│ when state.previousElement is
7│ Num previousElement if previousElement < elem -> { counts: state.counts + 1, previousElement: elem }
8│ _ -> { state & previousElement: elem }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The 2nd branch is a record of type:
{ counts : Num a, previousElement : [ Num (Num b) ]c }
But all the previous branches have type:
{ counts : Num a, previousElement : Num b }
I need all branches of a when to have the same type!
I don't really get the error about [ Num (Num b) ]c
. Can someone help?
I'll take a look in 15 mins @Yann Simon
I'm not exactly sure what went wrong @Yann Simon but this fixes it :)
measurements = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263 ]
increases =
List.walk measurements { counts: 0, previousElement: 600 } \state, elem ->
if state.previousElement < elem then
{ counts: state.counts + 1, previousElement: elem }
else
{ state & previousElement: elem }
increases
OK, but I'd like to use something else as 600
as initial state, like None
to start with an empty previous element. And then I need the when
right?
Yann Simon said:
Martin Janiczek said:
Hello! Trying Roc on 2021/01, starting out from examples/cli. Is there some working implemented str->num function? I tried out Str.toNum and Str.toU8 that I saw mentioned in the compiler/builtins/docs/*.roc but no luck so far
We mentioned that in #beginners > tutorial and the change is coming: https://github.com/rtfeldman/roc/pull/2108
I'm sorry for the confusion, my question was the other way round, the linked PR does Num->Str, I need Str->Num
@Yann Simon I see, matching with Some
(with if) and None
should work.
Matching with Num previousElement
does not work as you intend, I'd recommend reading the section on Numbers here.
Hey all, looking for a bit of advice on how to get up and running. I've got a hello world example here: https://github.com/Sourceless/advent-of-code-2021/blob/master/01/part1.roc -- I see that a lib is required to use some of the I/O actions, so I've symlinked to the platform
in examples/cli
in the Roc repo.
This example compiles and runs but produces no output:
``` $ roc part1.roc
:hammer: Rebuilding host... Done!
$ ```
There is however a blank line.
I'm running the latest nightly of Roc (the binary sat in my PATH) with cargo nightly on Ubuntu 20.04. Thanks in advance for any help and please forgive the stupid questions!
You might be running into the same issue I ran into a while ago : https://roc.zulipchat.com/#narrow/stream/231634-beginners/topic/tutorial/near/263096067
I've found that you just need to await something - so I'm making it await on Task.succeed {}
using your main
definition there gets me this:
thread '<unnamed>' panicked at 'index out of bounds: the len is 0 but the index is 0', compiler/mono/src/ir.rs:8208:35
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrac
Did you import pf.Task.{ await }
?
i didn't, i'll try that quickly
app "hello"
packages { base: "../examples/cli/platform" }
imports [ base.Task.{ await, succeed }, base.Stdout ]
provides [ main ] to base
main =
# Has to be the first line of every main
_ <- await (succeed {})
Stdout.line "I'm a roc application!"
that did it, many thanks @Shrikanth Upadhayaya
I see we have a few people in the AoC roc leaderboard :p
here's the id for newcomers: 482952-59f1582e
@Lucas Rosa Where do we use that ID?
on the AoC site, click [Leaderboard]
, then in the paragraph below the menu click [Private Leaderboard]
, you should see an input box to add that ID
Ah, that paragraph doesn't show up until you Log In. Thanks... just added myself.
baller
For anyone that has completed the advent of code for today in Roc, it would be great if you can send the link to your repo. That way other users who get stuck can take a look. Since roc has a number of rough edges at the moment, that would probably be very useful to others.
Here is a link to a gist. I'll probably end up creating a repo so I can have all the days together, but this is for today. This is my first time really using a functional language for something non-trivial, and I know at least a few things that I could have improved: https://gist.github.com/cbcc781860f5ad69b7c7bfe55087e6c6
I didn't do any reading in from a file, just copied the list of numbers since the Str.toNum builtin wasn't ready yet
I just used the cli platform for the platform
I'm still stuck. I've tried adding more type annotations to help the compiler, but nothing helps ;(
Option a : [ Some a, None ]
Aggr : { counts: Nat, previousElement: Option Nat}
walkStep: Aggr, Nat -> Aggr
walkStep = \state, elem ->
when state.previousElement is
Some previousElement if previousElement < elem -> { counts: state.counts + 1, previousElement: Some elem }
_ -> { state & previousElement: Some elem }
initialState: Aggr
initialState = { counts: 0, previousElement: None }
measurements = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263 ]
increases = List.walk measurements initialState walkStep
increases
gives the following error in the REPL:
thread 'main' panicked at 'internal error: entered unreachable code: Something had a Struct layout, but instead of a Record or TagUnion type, it had: Alias(`#UserApp.Aggr`, AliasVariables { variables_start: 424, all_variables_len: 0, type_variables_len: 0 }, 990)', cli/src/repl/eval.rs:184:21
or this error when compiling the roc file:
Mismatch in compiler/unify/src/unify.rs Line 1078 Column 13
Trying to unify two flat types that are incompatible: { 'counts' : Required(1152), 'previousElement' : Required(1137), }<1> ~ Apply(`Str.Str`, [])
thread 'main' panicked at 'internal error: entered unreachable code: symbol/layout `fx.Effect.effect_always_inner` ProcLayout { arguments: [Struct([]), LambdaSet(LambdaSet { set: [(`fx.Effect.effect_always_inner`, [Union(NonRecursive([[Union(NonRecursive([]))], [Builtin(Str)]]))])], representation: Struct([Union(NonRecursive([[Union(NonRecursive([]))], [Builtin(Str)]]))]) })], result: Union(NonRecursive([[Union(NonRecursive([]))], [Union(NonRecursive([]))]])) } combo must be in DeclarationToIndex', compiler/mono/src/borrow.rs:227:9
Same issue by changing walkStep
to:
walkStep = \state, _elem ->
state
I created a gist for using the WIP cli-file-io
branch for reading input: https://gist.github.com/shrik450/dea48e77ccacc3f6da6bf9538cd61bde
I ran into a few issues which I patched, so this should be helpful if you're trying to do it but can't get it working
ok very strange, I've started a new roc file from scratch, copy/paste everything step by step, and now it's compiling...
My solution, without reading inputs from file:
Shrikanth Upadhayaya said:
I created a gist for using the WIP
cli-file-io
branch for reading input: https://gist.github.com/shrik450/dea48e77ccacc3f6da6bf9538cd61bde
Cool! Could you merge trunk inside so that we can still use Num.toStr
?
It's not my branch, unfortunately
if you want to use both, you can vendor the platform code separately into whatever directory you're using
The only changes there are in the platform code
ok thx
I can confirm I can read the file (with the modification as I'm on macos)
Now I just need #beginners > Str.toNum :wink:
What's the policy on public repos with Roc code? Would it be okay to make Roc code public, or should I make my repo private until the language stabilizes?
I think public repos should be fine. I mean there are already a number of talks on roc. We mostly want to control how plausible it is for Roc to go viral and then for many people to be extremely annoyed because it isn't ready yet. But we are willing to accept new comers who happen upon the language.
Just want slow stable growth until it is more ready for the general internet. Public repos on github should be just fine. I wouldn't expect them to randomly go viral.
I've pushed my current code to github: https://github.com/yanns/roc-advent-of-code-2021/blob/main/day1/aoc_1.roc
sick
for those doing advent of code in Roc: how's it going? Has anyone gotten stuck or blocked on anything?
It's a great opportunity to find things to fix in the language, so please let us know about anything you trip over! :big_smile:
(Day 1 of AoC is my first Roc program, so my feedback is very untrained.)
I got stuck on this problem for a while:
jan@Jans-MacBook-Pro advent-of-code-2021 % ./solutions/day-1a-sonar-sweep/run_1a.sh
Finished dev [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/roc ../solutions/day-1a-sonar-sweep/solution_1a.roc`
Mismatch in compiler/unify/src/unify.rs Line 1078 Column 13
Trying to unify two flat types that are incompatible: Func([242, 252], 240, 221) ~ Func([104, 105, 117], 119, 120)
thread '<unnamed>' panicked at 'index out of bounds: the len is 0 but the index is 0', compiler/mono/src/ir.rs:8236:35
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
^C
[nix-shell:~/code/advent-of-code-2021/roc]$ exit
exit
jan@Jans-MacBook-Pro advent-of-code-2021 %
The problematic code was essentially this:
#!/usr/bin/env roc
app "hi"
packages { base: "../../roc/examples/cli/platform" }
imports [ base.Task.{ Task, await }, base.Stdout ]
provides [ main ] to base
main : Task {} *
main =
{} <- await Stdout.line "hi"
Stdout.line "nope"
My obvious-in-hindsight mistake was missing parentheses: await (Stdout.line "hi")
However, this panic is super confusing. Additionally, I feel like I've seen as many obtuse panics (like this one, but there's been others) as pretty-printed error/warning messages - this is offputting to a learner, though I imagine this is par for the course for WIP compilers.
I saw this panic about 10 times in my first 10 minutes of coding (likely from some fundamentally flawed line of code, like missing parentheses or something):
thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:116:45
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5
Ideas for improvement (not sure if possible):
Excellent feedback, thanks @JanCVanB! Can someone familiar with this code set up some issues?
I have the repo updated and can run cargo run repl
. what's the recommended way to get started? :) I tried the gist, but even with the patches it segfaults on thread 'main' panicked at 'not yet implemented: unhandled parse error IndentProvides(0, 14)', reporting/src/error/parse.rs:3148:14
Hi @Ju Liu, can you tell me which gist you are using?
this one :) https://gist.github.com/shrik450/dea48e77ccacc3f6da6bf9538cd61bde
"packages ...", "imports..." and "provides..." need to have four spaces before them.
thank you! now it just sits there
$ cargo run test.roc
Finished dev [unoptimized + debuginfo] target(s) in 0.89s
Running `target/debug/roc test.roc`
$ cat test.roc
app "solution"
packages { base: "../platform" }
imports [ base.Task.{ await }, base.Stdout, base.File ]
provides [ main ] to base
inputPath = "test.roc"
main =
_ <- await (Stdout.line "Trying to read file...")
task = File.readUtf8 inputPath
Task.attempt task \result ->
when result is
Ok input -> Stdout.line "Contents:\n\(input)"
Err _ -> Stdout.line "Failed to read input."
that branch is still WIP, although it should fail with an explicit error :laughing:
https://github.com/rtfeldman/roc/pull/2105#issuecomment-984236135
it's weird because it seems it's just stuck, maybe I should try straceing it and see what it's up to
I also encountered that:
inputPath = "/home/anton/gitrepos/extraroc/roc/examples/cli/Test.roc"
echo Echo.roc Files.roc platform README.md solution Test.roc
packages { base: "./platform" }
instead of packages { base: "../platform" }
I run with cargo run examples/cli/Test.roc
from the root of the repo.
Note that I also used Test.roc
everywhere instead of test.roc
Does that work for you @Ju Liu ?
uhh, good catch, it runs! :)
I had to apply the patches since I'm on OSX
this now works for me from the top-level of the repo
$ cat Test.roc
app "solution"
packages { base: "./examples/cli/platform" }
imports [ base.Task.{ await }, base.Stdout, base.File ]
provides [ main ] to base
inputPath = "./Test.roc"
main =
_ <- await (Stdout.line "Trying to read file...")
task = File.readUtf8 inputPath
Task.attempt task \result ->
when result is
Ok input -> Stdout.line "Contents:\n\(input)"
Err _ -> Stdout.line "Failed to read input."
have to run right now, thanks @Anton for showing me the light
Happy to help :)
hello everyone!
not sure where to write (first time using zulip) :smile:
I'm getting an error while using records as values for Dict
, is this a known issue?
$ roc repl
» Dict.single 0 {a: 1, b: 1} |> Dict.get 0
thread 'main' panicked at 'Error in alias analysis: error in module ModName("UserApp"), function definition FuncName("\x06\x00\x00\x00\x04\x00\x00\x00eiGJ\xf5B\x11="), definition of value binding ValueId(13): expected type '(((), ()),)', found type '((),)'', compiler/gen_llvm/src/llvm/build.rs:4019:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Hi @Emiliano Bovetti,
I could not find this in the issues, I'll make a new one. Thanks for reporting it!
I wrote a program to solve the tasks of Day 1 with Roc.
The first task of Day 1 is solved when removing lines 9 and 10 of that program. For that task, the program prints the correct answer for exampleInput
as well as largeInput
.
For the second task of Day 1 the program prints the correct result only for exampleInput
. When using largeInput
the program exits with a segmentation fault.
Are you building with --optimize
Probably getting stack overflow on large inputs otherwise.
Originally I was not. I now tried with --optimize
but it still segfaults.
One more test, can you run ulimit -s unlimited
before running the executable?
Will enable unlimited stack space for that terminal session
Also segfaults with unlimited stack space.
hmm...probably an actual bug...cool
To be fair requiring unlimited stack space is definitely also a bug, but that is more general to work on things than specific bugs.
Hmm...neither run on my m1 mac. That suggests it is likely some sort of invalid memory bug. arm is a lot more picky around that kind of stuff.
Yeah, looks to be some sort of refcounting issue, maybe a double free
I just spent 2 hours debugging type mismatches in my AoC code, and although I've found some mistakes, I don't feel like my code is close to working. Therefore, I want to take a step back and ask... How should I be developing Roc code? I feel like my workflow must be flawed.
My workflow:
Where am I going wrong? I'm asking honestly, not flaming, because the workflow feels wrong.
I finished days 1 & 2 with this workflow, but I'm stuck on debugging my day 9 code.
Here's my day 1 code: https://github.com/JanCVanB/advent-of-code-2021 (will push more days soon)
are you using roc check Foo.roc
? using check
over build
should improve error messages
most crashes are because of earlier type checking problems leading to edge cases during code gen
and check
only runs the type checker
I'll add a tip to use roc check
to the README and getting started files.
Folkert de Vries said:
are you using
roc check Foo.roc
? usingcheck
overbuild
should improve error messages
No, I didn't know that existed! I'll try that, thanks.
What is the best way to read complex numeric data into an examples/cli/
-based Roc module from a file or string? https://github.com/rtfeldman/roc/issues/2188 is giving me trouble with AoC day 9, which has this input data format (for a 2D matrix of elevation data, where input(x, y) ∈ [0, 9]
):
Screen-Shot-2021-12-12-at-4.16.06-AM.png
I really don't want to semi-manually convert that into a hard-coded List
like heightMeasurements = [ [ 6, 6, 8, 9, 9, 2, ... ], [ ... ], ... ]
, but I don't mind copy/pasting it into a hard-coded Str
like heightMeasurements = "668992...\n..."
. However, I can't seem to split that Str without a segfault. Any tips appreciated! :smile:
Ooh, I just found https://gist.github.com/shrik450/dea48e77ccacc3f6da6bf9538cd61bde (thank you @Shrikanth Upadhayaya) via https://github.com/yanns/roc-advent-of-code-2021/blob/main/day1/aoc_1.roc (thank you @Yann Simon) - this might solve my file I/O needs, though I'll still need Str
splitting...
Str.split or something might exist. Str.toI64 just got merged
Hooray for Str.toI64! Yes, Str.split exists, but it doesn't seem to work with an empty-string delimiter :/
@JanCVanB that's probably a quick fix! can you file a bug?
Sure! Should I enhance https://github.com/rtfeldman/roc/issues/2188 or file something new?
oh nm that's good enough
although, I just realized that Str.split
with an empty string should likely be a no-op :thinking:
it would be easy to say "we should make it split on a character boundary" such that "1234"
would become [ "1", "2", "3", "4" ]
but that devolves quickly into a pile of Unicode edge cases (e.g. what if there are a bunch of emojis with modifiers, or multi-code-point compound characters) which I don't think should be in scope for a simple function like split
Oh, lol, so I can just List.map
a Str
... nice.
however, I think there's an easier solution: Str.split
on newlines to get a List Str
of lines, and then for each line, do Str.toUtf8
to get a List U8
the List U8
won't be quite what you want, because they'll be ASCII bytes rather than the actual numbers you want, so you'll have to subtract 48 from each of them
to get the actual number
but then you'll have the actual number as a U8
!
Modifying my example in the above issue, when I change Stdout.line (Str.joinWith (Str.split "abc" "") ", ")
to Stdout.line (Str.joinWith "abc" ", ")
, I get
[nix-shell:~/code/advent-of-code-2021]$ ./roc/target/release/roc example.roc
🔨 Rebuilding host...
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
The 1st argument to joinWith is not what I expect:
12│ Stdout.line (Str.joinWith "abc" ", ")
^^^^^
This argument is a string of type:
Str
But joinWith needs the 1st argument to be:
List Str
────────────────────────────────────────────────────────────────────────────────
Done!
Roc hit a panic: Hit an erroneous type when creating a layout for `3.IdentId(5)`
[nix-shell:~/code/advent-of-code-2021]$
However, Stdout.line (Num.toStr (List.sum (List.map (Str.toUtf8 "123") \x -> x - 48)))
prints 6
! Thank you!
Whoa... While cleaning that up by replacing \x -> x - 48
with Str.toI64
, I just experienced a level up in my Roc comfort :smiley: #Pipes4Life
#!/usr/bin/env roc
app "example"
packages { base: "roc/examples/cli/platform" }
imports [ base.Stdout, base.Task.{ await, Task } ]
provides [ main ] to base
main : Task {} *
main =
# This extra Stdout.line call is required. See GH issue #2151.
_ <- await (Stdout.line "")
"123"
|> Str.toUtf8
|> List.map \u ->
when Str.fromUtf8 [u] is
Err _ -> "!"
Ok s -> s
|> List.map \s ->
when Str.toI64 s is
Err _ -> -999
Ok i -> i
|> List.sum
|> Num.toStr
|> Stdout.line
That prints 6
:heart_eyes:
nice!!! :smiley:
Very awesome!
Should this work?
[1, 2, 3]
|> List.map \x -> x * 2
I'm getting an internal error: entered unreachable code
panic about it, so I can't tell if I'm making a syntax mistake
I think the anonymous function needs brackets.
That works! Thank you :D
Because function arguments are also separated by spaces.
You're welcome :)
So now that that panic is gone, I have a Roc fluency problem: How can I improve this function to support parsing negative integers?
parseIntegers : List Str -> List I64
parseIntegers = \integerStrings ->
integerStrings
|> List.map (\s -> Str.toI64 s)
|> List.map \x ->
when x is
Ok i -> i
Err _ -> -1
|> List.keepIf (\i -> i > 0)
I'm using the -1
hack to prevent the output type having Result
s in it, but there must be a better way.
Maybe the output type having Result
s in it is actually best? Maybe I need to get used to Err
s bubbling up from every subroutine...
However, in this case I simply want to throw away strings that aren't valid integers. Surely that should be possible:
parseIntegers ([ "no", "way", "-123", "456", "789jk" ]) == [ -123, 456 ]
Oh I found something useful, List supports keepOks
.
but it does not appear to be implemented yet.
I think this should work:
parseIntegers : List Str -> List I64
parseIntegers = \integerStrings ->
integerStrings
|> List.map (\s -> Str.toI64 s)
|> List.keepIf \x ->
when x is
Ok _ -> True
Err _ -> False
Better version:
parseIntegers : List Str -> List I64
parseIntegers = \integerStrings ->
integerStrings
|> List.keepOks (\s -> Str.toI64 s)
Interesting, I would expect this [1, 2, 3] |> List.map \x -> x * 2
to work. Is it a bug or is it intended?
Uhu [1, 2, 3] |> List.map \x -> x * 2
works in the repl.
@Anton I get
[nix-shell:~/code/advent-of-code-2021]$ ./roc/target/release/roc check solutions/day-1-sonar-sweep/solution_1a.roc
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
Something is off with the body of the parseIntegers definition:
8│ parseIntegers : List Str -> List I64
9│ parseIntegers = \integerStrings ->
10│> integerStrings
11│> |> List.map (\s -> Str.toI64 s)
12│> |> List.keepIf \x ->
13│> when x is
14│> Ok _ -> True
15│> Err _ -> False
This keepIf call produces:
List (Result I64 [ InvalidNumStr ]b)
But the type annotation on parseIntegers says it should be:
List I64
────────────────────────────────────────────────────────────────────────────────
[nix-shell:~/code/advent-of-code-2021]$
:/
Oh right, the results are all Ok but they are not unwrapped. The shorter alternative I posted does work right?
sidenote: Result.isOk
and Result.isErr
are implemented but are not in the builtins/docs. I'll add them now.
Oh, whoa, I didn't expect that to work because I thought List.keepOks
wasn't implemented yet (also missing from builtins/docs). Your shorter alternative works like a charm!
List.keepOks
is going to be a huge help for AoC, since inputs are highly controlled
Actually, we can make it even cleaner by making it slightly point-free-er: parseIntegers = \integerStrings -> integerStrings |> List.keepOks Str.toI64
I wonder if there's a way to make it totally point-free by eliminating the need for integerStrings
...
point-free requires currying usually
roc doesn't do that. point-free is cute but honestly it can lead to some confusing code especially for people not familiar with ML style languages
@JanCVanB regarding the "entered unreachable code" panic you saw - any time you see that error message, it's definitely a compiler bug! It means the compiler went down a code path that we thought was unreachable.
Would you mind reporting that one as an issue?
and given the location it's probably some error in llvm codegen, which is particularly interesting
It's really cool to see this much roc code being used for stuff :D
I'm glad y'all aren't tired of me spamming my beginner questions for my beginner use case :)
oh it's amazing! :smiley:
the more the better!
@JanCVanB not at all, in a way you’ve used more roc than all of us, we’re the beginners
@Richard Feldman Reported: https://github.com/rtfeldman/roc/issues/2205
Because of a memory issue with large lists I tried to use my own type for linked lists and ran into three separate problems.
The first problem can be reproduced by replacing the hello-world example with the following program.
LinkedList elem : [Empty, Prepend (LinkedList elem) elem]
prepend : LinkedList elem, elem -> LinkedList elem
prepend = Prepend
single : elem -> LinkedList elem
single = \elem -> prepend Empty elem
main =
nested = single (single 42)
"Hello, World!\n"
This program produces the following panic:
thread 'main' panicked at 'internal error: entered unreachable code: symbol/layout `#UserApp.1` ProcLayout { arguments: [Union(NullableUnwrapped { nullable_id: false, other_fields: [RecursivePointer, Builtin(Int(I64))] }), Builtin(Int(I64))], result: Union(NullableUnwrapped { nullable_id: false, other_fields: [RecursivePointer, Builtin(Int(I64))] }) } combo must be in DeclarationToIndex', compiler/mono/src/borrow.rs:227:9
The program runs as intended when inlining prepend
or single
or when changing the definition of prepend
as shown below.
The second issue can be reproduced by adding/changing the following definitions:
empty : LinkedList *
empty = Empty
prepend : LinkedList elem, elem -> LinkedList elem
prepend = \elems, elem -> Prepend elems elem
wrap : LinkedList elem -> LinkedList (LinkedList elem)
wrap = \elems ->
when elems is
Empty -> empty
Prepend tail head -> tail |> wrap |> prepend (single head)
main =
nested = wrap (single 42)
"Hello, World!\n"
Now executing the program results in the following error:
Application crashed with message
Hit an unresolved type variable 103 when creating a layout for `#UserApp.empty` (var 102)
Shutting down
The error goes away when replacing empty
with Empty
in the definition of wrap
.
The third issue is a stack overflow when compiling (or running roc check
) on the following definition:
fromList : List elem -> LinkedList elem
fromList = \elems -> List.walkBackwards elems Empty Prepend
Compilation works fine when replacing Empty
with empty
in the definition of fromList
.
By using the described work-arounds, I was able to change my program for AoC Day 1 to use linked lists instead of built-in lists to solve the problem for the large input!
Should I create issues for the described problems or are they expected / already known?
issues would be most appreciated! :smiley:
Richard Feldman said:
issues would be most appreciated! :smiley:
Just filed issues 2215, 2216, and 2217
awesome, thank you so much!
Roc is feeling reeeeeeal smooth! https://github.com/JanCVanB/advent-of-code-2021/blob/main/solutions/day-2-dive/solution_2_part_2.roc
(Spoiler alert for AoC participants, this is a solution for Day 2 Part 2)
Pipe chains are super readable, the Result
builtins are intuitive... and though I've hit a lot of compiler bugs, there are always acceptable workarounds.
:) yay
Today's multiverse problem (part 2) seems like it could cause some stack overflows, though I imagine there's some optimization(s) that could help somehow. However, even with a quick recursion-ending condition (maxScore=5, instead of 21), I'm getting a new kind of compiler error: Stored value type does not match pointer operand type! ... Function "..." failed LLVM verification in NON-OPTIMIZED build. ... thread 'main' panicked at '😱 LLVM errors when defining function ...
. I'll create a GH issue.
Whoa, it's due to True
/ False
literals...
something to watch out for is that True
itself has type [ True ]*
, not Bool
you may need some type annotations sometimes to make it a boolean
Oh, that's interesting!
I posted an issue for it: https://github.com/rtfeldman/roc/issues/2254
Essentially, something works with { oldRecord & thing: True, a: b, x: y }
but not with { oldRecord & thing: False, a: b, x: y }
right, I think you can fix it quickly with a type annotation to coerce the value to be a bool
Was just about to ask that, thanks
@Folkert de Vries The problem starts with state initialization. This code:
InitialSetup : { player1Position: Nat, player2Position: Nat }
Multiverse : { player1WinCount: Nat, player2WinCount: Nat, universes: List Universe }
Universe : { isPlayer1sTurn: Bool, player1Position: Nat, player1Score: Nat, player2Position: Nat, player2Score: Nat }
initializeMultiverse : InitialSetup -> Multiverse
initializeMultiverse = \setup ->
universe : Universe
universe = { isPlayer1sTurn: True, player1Position: setup.player1Position, player1Score: 0, player2Position: setup.player2Position, player2Score: 0 }
{ player1WinCount: 0, player2WinCount: 0, universes: [universe] }
gets this roc check
error:
The body is a record of type:
{ player1WinCount : Num (Integer Natural),
player2WinCount : Num (Integer Natural), universes : List {
isPlayer1sTurn : Bool, player1Position : Nat, player1Score : Nat,
player2Position : Nat, player2Score : Nat } }
But the type annotation on initializeMultiverse says it should be:
{ player1WinCount : Nat, player2WinCount : Nat,
universes : List Universe }
Do records not type well?
I meant
isPlayer1sTurn: Bool
isPlayer1sTurn = True
It looks to me that both of the supposedly-mismatched types above have Bool
in them, is that not sufficient?
Adding those two lines doesn't help:
InitialSetup : { player1Position: Nat, player2Position: Nat }
Multiverse : { player1WinCount: Nat, player2WinCount: Nat, universes: List Universe }
Universe : { isPlayer1sTurn: Bool, player1Position: Nat, player1Score: Nat, player2Position: Nat, player2Score: Nat }
initializeMultiverse : InitialSetup -> Multiverse
initializeMultiverse = \setup ->
isPlayer1sTurn : Bool
isPlayer1sTurn = True
universe : Universe
universe = { isPlayer1sTurn: isPlayer1sTurn, player1Position: setup.player1Position, player1Score: 0, player2Position: setup.player2Position, player2Score: 0 }
{ player1WinCount: 0, player2WinCount: 0, universes: [universe] }
(same check error)
oh, I see what's happening
somehow Universe
is not recognized as an alias
ah, this is the alias ordering bug
try putting Universe
at the top
due to a bug, aliases must be defined in their usage order (so no use before definition)
Wowwwwww you're right! Flipping the order of the Multiverse
and Universe
definitions fixes it!
Now I just have to optimize it so that it won't take... (checks calculator)... a week to run.
Glad you're posing this stuff, Jan, it's really interesting, keep up the good work!
Checking ~ 1 quintillion board game states sure takes a while... :laughing:
That's a handful... Maybe enough to not compete with bad code generation/recursion issues
This is my output
https://gist.github.com/satotake/0e5f4cb69924927cbce379212e102081
not completed (day1 - day14)
I might add the others but I am starting feeling that they will be almost same in terms of testing roc.
Seeing @Lucas Rosa 's private leaderboard, Arkham
is legendary.
You might have written the most AoC Roc code of anyone, since I'm not sure that everyone in that leaderboard used Roc!
JanCVanB said:
since I'm not sure that everyone in that leaderboard used Roc!
possible ... but really?.
Anyway, the conversations in this channel motivated me to do so. thanks!
I was using zig but then just quit after day 3 cause I was like why am I doing this
zig's comptime is interesting https://expandingman.gitlab.io/tvu-compare/
It might have been also good for me to try AoC in zig or rust to understand roc codebase
hah! from time to time I re-compile roc, fix any error that come up on the platform I stitched up and try my day 1 advent of code 2021 program. it finally worked :tada:
app "day-01"
packages { pf: "cli-platform" }
imports [ pf.Task.{ Task, await }, pf.Stdout, pf.File ]
provides [ main ] to pf
main =
handle <- File.withOpen "day-01-input.txt"
stringLines <- await (File.lines handle)
lines = stringLines |> List.map \n -> (Str.toNat n |> Result.withDefault 0)
increases = lines
|> List.walk { count: 0, prev: None } \res, m ->
when res.prev is
Some p ->
count = res.count + (if p < m then 1 else 0)
{ count, prev: Some m }
None -> { count: res.count, prev: Some m }
r = Num.toStr increases.count
Stdout.line "res: \(r)"
Nice :)
Last updated: Jul 05 2025 at 12:14 UTC