Stream: ideas

Topic: basics/prelude


view this post on Zulip Georges Boris (May 13 2023 at 15:06):

folks, this is less of an idea and more of a question

I noticed we don't have an equivalent of elm's Basics or haskell's Prelude - that means that nothing gets imported by default, right?

however, we have access to functions like |> and + - the idea here is that these won't be seen as functions in Roc and will just be defined and documented as part of the syntax?

the upside of having something like a prelude apart from having an obvious place to look for documentation is that perhaps we could solve the boolean problem by just having Bool.true and Bool.false be part of that package (even if boolean specific functions would still live under the Bool module) this wouldn't be that different than having ++ available always even tho we could make an argument that it should live under List.concat

thoughts? has this been discussed before?

view this post on Zulip Brendan Hansknecht (May 13 2023 at 15:18):

I don't think it has been discussed before

view this post on Zulip Brendan Hansknecht (May 13 2023 at 15:20):

Also, interesting comment on what is considered a function. Personally I don't really consider + or ++ as functions. The main distinction is that functions are something that users can create. These are not. Just like |> or <- I look at those more as convenient syntax sugar. a + b is syntax sugar for Num.add a b (with some precedence rules to be fair).

view this post on Zulip Brendan Hansknecht (May 13 2023 at 15:22):

Personally I really like the prefixes, but that may not exactly be what you mean here. As in, I like seeing List.append instead of just append. I am not very familiar with elm or Haskell prelude. What is the scope of what it would import if applied to roc?

view this post on Zulip Georges Boris (May 13 2023 at 15:32):

https://package.elm-lang.org/packages/elm/core/latest/Basics for reference

view this post on Zulip Georges Boris (May 13 2023 at 15:32):

I'm 100% not saying that we should include everything Elm does

view this post on Zulip Richard Feldman (May 13 2023 at 15:32):

I noticed we don't have an equivalent of elm's Basics or haskell's Prelude - that means that nothing gets imported by default, right?

all the builtin modules (e.g. Str) get imported by default, and all their types get exposed

view this post on Zulip Richard Feldman (May 13 2023 at 15:33):

I never wrote this down anywhere, but I had an explicit goal of not having a Basics module in Roc :big_smile:

view this post on Zulip Georges Boris (May 13 2023 at 15:33):

but having a central place where we define things that are always available in scope could also be useful for something like Bool.true

view this post on Zulip Richard Feldman (May 13 2023 at 15:33):

Bool is one of the builtin modules

view this post on Zulip Richard Feldman (May 13 2023 at 15:33):

so Bool.true is in scope because the Bool module is always imported

view this post on Zulip Georges Boris (May 13 2023 at 15:34):

I know - I'm saying that it could be Basics.true

view this post on Zulip Georges Boris (May 13 2023 at 15:34):

so true and false would always be in scope

view this post on Zulip Georges Boris (May 13 2023 at 15:34):

even though they are just opaque types

view this post on Zulip Richard Feldman (May 13 2023 at 15:35):

see https://docs.google.com/document/d/1a51n7eIEbPjCWnGaL-pWbZBsRfi55GVQwIdPQTUu49Q under "Future Optionality" - that design has downsides

view this post on Zulip Richard Feldman (May 13 2023 at 15:35):

separately though, it was a longstanding goal to never have any values imported unqualified by default (like Elm's Basics does)

view this post on Zulip Richard Feldman (May 13 2023 at 15:35):

so this is something I actively don't want to change

view this post on Zulip Richard Feldman (May 13 2023 at 15:36):

part of the reason for this is that I want the rules to be simple:

that's it, those are the rules

view this post on Zulip Richard Feldman (May 13 2023 at 15:37):

also, as noted in the doc - even if we made an exception for true and false (and again, it is an explicit goal not to have any exceptions) then that still wouldn't help in pattern matching

view this post on Zulip Richard Feldman (May 13 2023 at 15:37):

because no matter what's exposed, true -> always means "a variable which I have happened to name true right here"

view this post on Zulip Richard Feldman (May 13 2023 at 15:38):

unless you make true a reserved language keyword which has special meaning in patterns

view this post on Zulip Richard Feldman (May 13 2023 at 15:40):

so in my mind, the two designs that make sense for Bool are:

view this post on Zulip Brendan Hansknecht (May 13 2023 at 15:41):

Can someone import Bool.true directly at the top of the file or are builtins now allowed to be explicitly imported?

view this post on Zulip Richard Feldman (May 13 2023 at 15:41):

you can always do that, sure

view this post on Zulip Richard Feldman (May 13 2023 at 15:42):

as in like imports [Bool.{ true, false }]

view this post on Zulip Brendan Hansknecht (May 13 2023 at 15:42):

Yeah, does that work?

view this post on Zulip Richard Feldman (May 13 2023 at 15:42):

as far as I know yeah

view this post on Zulip Richard Feldman (May 13 2023 at 15:42):

I haven't tried it in awhile though haha

view this post on Zulip Brendan Hansknecht (May 13 2023 at 15:42):

Ok. Just never tested it because of the builtin imports.

view this post on Zulip Richard Feldman (May 13 2023 at 15:42):

for what it's worth, so far the Bool.true and Bool.false experiment has been a success in my view

view this post on Zulip Richard Feldman (May 13 2023 at 15:44):

as evidence of the success of the experiment, as far as I can remember, the majority of Zulip discussion around Bool.true and Bool.false has occurred in the past week, and has been motivated not by their being confusing or hard to use but rather because of their impact on unrelated syntax ideas :smiley:

view this post on Zulip Richard Feldman (May 13 2023 at 15:52):

(at least since we implemented it; of course there was more discussion before then in the design phase)

view this post on Zulip Georges Boris (May 13 2023 at 15:59):

uhn - I get all of this and mostly agree.

I just feel like the weirdness budget discussions are not completely balanced. When we discussed the different if syntax recently the argument against it was basically familiarity and one-line syntax (which could be worked on).

Bool.true is - in my opinion - the weirdest part of Roc syntax by far (I'm both familiar with ML and C languages) and I'm not sure that "booleans are usually the worst but easier way of modeling something" holds as much as it does with Maybe.

view this post on Zulip Richard Feldman (May 13 2023 at 16:00):

yeah I agree it's weird :thumbs_up:

view this post on Zulip Georges Boris (May 13 2023 at 16:00):

but getting back to the basics module - got it! so documentation on pipelines / infix functions / would leave in it's own place. possibly "around syntax" or something, right?

view this post on Zulip Richard Feldman (May 13 2023 at 16:01):

a reason I'm a lot more okay with Bool.true and Bool.false being weird than I am with if being weird is that literally writing out Bool.true and Bool.false should come up much less often than if if you're modeling data with tag unions instead of bools (which is the recommended way to do it)

view this post on Zulip Richard Feldman (May 13 2023 at 16:01):

e.g. if you're doing boolean logic (which is when I'd say they're most valuable), such as && and ||, you basically never write out actual true/false, you're just combining the outputs of functions that returned bools

view this post on Zulip Richard Feldman (May 13 2023 at 16:02):

if you have Bool in your data model, then you write out Bool.true and Bool.false all the time, which is weird - but that's kind of the point of the incentive; if it feels weird, then there's an incentive to use tags instead :big_smile:

view this post on Zulip Georges Boris (May 13 2023 at 16:09):

wouldn't you say that if booleans are not usually the best practice to model the data then pattern matching would also be usually the best way to deal with logic flow? (so using if/then/else should perhaps be less ergonomic to push users to the proper modeling strategies?)

view this post on Zulip Georges Boris (May 13 2023 at 16:10):

(the subject is drifting I know :sweat_smile:)

view this post on Zulip Brendan Hansknecht (May 13 2023 at 16:14):

I don't think so. Data modeling is different than asking questions about your data. if is used for asking a yes or no question about the data you have. Even if it is model without bools

view this post on Zulip Georges Boris (May 13 2023 at 16:24):

I can agree with that but, for instance, in Elixir where I have more expressive ways of dealing with control flow, ifs are usually less readable way of doing that

view this post on Zulip Georges Boris (May 13 2023 at 16:24):

boolean checks usually stay at pattern matching guards (note that Elixir can have functions with multiple definitions for different matches, similar to Haskell)

view this post on Zulip Brendan Hansknecht (May 13 2023 at 16:38):

Yeah, that is really different though due to guards directly on function parameters. I am not sure it maps. Though I have only done a little elixir a long time ago.

view this post on Zulip Brendan Hansknecht (May 13 2023 at 16:39):

Like they have a different and more powerful structure that doesn't exist in roc.


Last updated: Jun 16 2026 at 16:19 UTC