roc icon indicating copy to clipboard operation
roc copied to clipboard

Builtins to implement

Open rtfeldman opened this issue 4 years ago • 21 comments

Builtins to implement

These are some builtins we haven't yet implemented. When implementing a builtin, please:

  1. Make an issue for it and and assign it to yourself so no one accidentally starts implementing your builtin after you've started!
  2. Put all the necessary changes for adding your builtin in the same PR, with no extraneous changes unrelated to adding the builtin. Then, include the name of the module and builtin (for example, List.dropAt) in the title of the PR. This allows other contributors to find your PR later and use it as an example when they are trying to implement their first builtins.

Num

  • [x] maxU128 : U128
  • [x] toI8 : Int * -> I8
  • [x] toI16 : Int * -> I16
  • [x] toI32 : Int * -> I32
  • [x] toI64 : Int * -> I64
  • [x] toI128 : Int * -> I128
  • [x] toU8 : Int * -> U8
  • [x] toU16 : Int * -> U16
  • [x] toU32 : Int * -> U32
  • [x] toU64 : Int * -> U64
  • [x] toU128 : Int * -> U128
  • [x] toF32 : Num * -> F32
  • [x] toF64 : Num * -> F64
  • [ ] parseI16 : List U8, Endi, Nat -> Result I16 [ NotEnoughBytes ]*
  • [ ] parseU16 : List U8, Endi, Nat -> Result U16 [ NotEnoughBytes ]*
  • [ ] parseI32 : List U8, Endi, Nat -> Result I32 [ NotEnoughBytes ]*
  • [ ] parseU32 : List U8, Endi, Nat -> Result U32 [ NotEnoughBytes ]*
  • [ ] parseI64 : List U8, Endi, Nat -> Result I64 [ NotEnoughBytes ]*
  • [ ] parseU64 : List U8, Endi, Nat -> Result U64 [ NotEnoughBytes ]*
  • [ ] parseI128 : List U8, Endi, Nat -> Result I128 [ NotEnoughBytes ]*
  • [ ] parseU128 : List U8, Endi, Nat -> Result U128 [ NotEnoughBytes ]*
  • [ ] parseF32 : List U8, Endi, Nat -> Result F32 [ NotEnoughBytes ]*
  • [ ] parseF64 : List U8, Endi, Nat -> Result F64 [ NotEnoughBytes ]*
  • [ ] parseNat : List U8, Endi, Nat -> Result Nat [ NotEnoughBytes ]*
  • [ ] parseDec : List U8, Endi, Nat -> Result Dec [ NotEnoughBytes ]*

List

  • [x] #2001
  • [x] #1896
  • [x] #2504
  • [x] walkBackwardsUntil : List elem, state, (state, elem -> [ Continue state, Stop state ]) -> state
  • [x] walkFrom : List elem, Nat, state, (state, elem -> state) -> state (starts walking at the given Nat index) (#4346)
  • [x] walkFromUntil : List elem, Nat, state, (state, elem -> [ Continue state, Stop state ]) -> state (#4346)
  • [ ] sortAscBy : List elem, (elem -> Num *) -> List elem
  • [ ] sortDescBy : List elem, (elem -> Num *) -> List elem

Result

  • [ ] map2 : Result a err, Result b err, (a, b -> c) -> Result c err
  • [ ] map3 : Result a err, Result b err, Result c err, (a, b, c -> d) -> Result d err
  • [ ] map4 : Result a err, Result b err, Result c err, Result d err, (a, b, c, d -> e) -> Result e err
  • [ ] map5 : Result a err, Result b err, Result c err, Result d err, Result e err, (a, b, c, d, e -> f) -> Result f err
  • [ ] map6 : Result a err, Result b err, Result c err, Result d err, Result e err, Result f err, (a, b, c, d, e, f -> g) -> Result g err
  • [ ] map7 : Result a err, Result b err, Result c err, Result d err, Result e err, Result f err, Result g err, (a, b, c, d, e, f, g -> h) -> Result h err
  • [ ] map8 : Result a err, Result b err, Result c err, Result d err, Result e err, Result f err, Result g err, Result h err, (a, b, c, d, e, f, g, h -> i) -> Result i err
  • [ ] mapBoth : Result ok1 err1, (ok1 -> ok2), (err1 -> err2) -> Result ok2 err2
  • [x] try : Result before err, (before -> Result after err) -> Result after err
  • [x] onErr : Result ok before, (before -> Result ok after) -> Result ok after
  • [x] #1954
  • [x] #1965

Str

  • [x] withCapacity : Nat -> Str
  • [ ] dropPrefix : Str, Str -> Result Str {}
  • [ ] dropSuffix : Str, Str -> Result Str {}
  • [x] #3251
  • [x] #1972

rtfeldman avatar Nov 08 '20 15:11 rtfeldman

Are any of these functions worth including in List?

I've been maintaining elm-community/list-extra over the years, Ive gotten to see which List.Extra functions Elm people seem to like. Here are the "all stars" of List.Extra imo; the functions that seem to get a lot of use and attention:

unique : List elem -> List elem
uniqueBy : List elem, (elem -> Str) -> List elem

group : List elem -> List { first : elem, rest : List elem }
groupWhile : List elem, (elem -> elem -> Bool) -> List { first : elem, rest : List elem }

# groupsOf [ 1, 2, 3, 4, 5, 6, 7 ] 3 == [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
groupsOf : List elem, Int -> List (List elem)

# greedyGroupsOf [ 1, 2, 3, 4, 5, 6, 7 ] 3 == [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7 ] ]
greedyGroupsOf : List elem, Int -> List (List elem)

List.Extra is by definition the functions that didn't make the cut into Elm, so I could understand if thats the case in Roc too. Maybe now is a good time to re-evaluate.

Chadtech avatar Mar 18 '21 06:03 Chadtech

divFloor is already implemented in compiler/builtins/src/std.rs

matthiasbeyer avatar Oct 27 '21 12:10 matthiasbeyer

I've got a PR out for Str.trim. I could add trimLeft and trimRight after that, or leave those as nice intro issues. It would be nice to implement trim in terms of trimLeft and trimRight, or all three of those and dropPrefix/dropSuffix in terms of compiler-private Roc functions.

Giesch avatar Oct 28 '21 16:10 Giesch

@Giesch if you want to go for trimLeft and trimRight, I'd say go for it! I think Str.trim can be faster if it's not implemented in terms of trimLeft and trimRight though, so I'd leave that as-is! 😄

rtfeldman avatar Nov 04 '21 02:11 rtfeldman

Is it necessary to include Str, Dict and Set as builtin? All three types can be implemented in Roc with List and Num.

I'd say make them part of the standard library written in Roc, not written in Zig.

There are way too many builtin symbols IMO. For example, all we need for List are

  • get
  • set
  • insert
  • remove
  • len

The rest can be written in Roc.

iacore avatar Nov 10 '21 06:11 iacore

I think we should define clearly what should go in where of:

  1. Compiler built (in zig/rust)
  2. Standard library (in roc)
  3. Platform

Let's say I want to write commerce software that deal with currency. I want to make Float backed by DEC64 for no loss in precision in decimal. How do I swap out the implementation of Float and expect all other functions to work?

iacore avatar Nov 10 '21 06:11 iacore

Is it necessary to include Str, Dict and Set as builtin?

Str yes, because the small string optimization is important for Roc since we don't use tracing GC with a bump-allocated nursery. It's not possible to implement that optimization in pure Roc.

Even if that weren't the case, Str would still be an opaque type which differs from List U8 in that it should have validated UTF-8 bytes. String literals should compile to Str rather than List U8, and it should be possible to have a Str -> List U8 conversion function, but the other way around should require a Result for UTF-8 validation.

Dict and Set depend on how https://github.com/rtfeldman/roc/issues/1955 turns out!

Standard library (in roc)

The Roc standard library refers to the builtins. The reason I chose the term builtins is to emphasize the fact that in Roc, the implementation of the standard library is built into the compiler. 😄

(It needs to be so that we can add extra metadata that gets used behind the scenes in compiler performance optimizations. That metadata should not be exposed outside the compiler!)

There are way too many builtin symbols IMO.

The priority with builtin types is for them to have nice Roc APIs and to run as fast as possible under the hood. I'm fine with however many symbols that ends up requiring!

Let's say I want to write commerce software that deal with currency.

We have a builtin Dec type for that. It's only partially implemented if you're looking for something to work on!

See https://github.com/rtfeldman/roc/pull/1494#issuecomment-896958053 for the most recent developments.

rtfeldman avatar Nov 10 '21 22:11 rtfeldman

For the map<N> implementations, is there any way we can have those magically auto-generated by the compiler? Seems pretty silly to not generalize that.

joshuawarner32 avatar Dec 17 '21 01:12 joshuawarner32

@matthiasbeyer Thanks for your comment. I've marked Num.divFloor as done, hopefully that's correct. @rvcas Thanks for your PR! I've marked Num.toStr as done, hopefully that's correct.

kili-ilo avatar Dec 22 '21 05:12 kili-ilo

Should the request for Num.fromStr be removed, in favor of using the more-specific and already-implemented Str.to* functions (Str.toI64, Str.toU8, Str.toNat, etc.)?

kili-ilo avatar Jan 20 '22 04:01 kili-ilo

In this case I think we'd rather have one Num.fromStr : Num * -> Str that works on any numeric type you give it.

Unlike some of the other scenarios we've talked about, I don't think there's anything particularly error-prone about the more flexible Num * design in this case, so might as well have one flexible function!

rtfeldman avatar Jan 20 '22 05:01 rtfeldman

What would be the type of Num.fromStr -1, if it must be signed? Would the compiler error on Num.fromStr -1 |> functionThatRequiresAU8?

Should the annotation instead be Num.fromStr : Num * -> Result (Num *) [ InvalidNumStr ]*, to match the Err cases of Str.toI8 and its friends (for situations like Num.fromStr "-200_000_000_000_000_000_000_000_000_000_000_000_000" that don't fit in any number type)?

(Should I move this Num.fromStr discussion to its own issue? 😛)

kili-ilo avatar Jan 20 '22 05:01 kili-ilo

Sorry, my mistake - for some reason I was thinking of Num.toStr : Num * -> Str and not fromStr (Num * -> Str would be a very strange type for a fromStr function!)

My excuse is that it's past midnight here. 😆

Anyway, I think you're right - we should open a separate issue for this, and also that we should probably have individual functions - one for each numeric type - to convert a string to that numeric type.

rtfeldman avatar Jan 20 '22 05:01 rtfeldman

@rtfeldman Mind if I delete all completed tasks in the top comment? I don't know GH best practices for long task lists, but since more than half of the tasks are completed, it seems helpful to trim it down for clarity. (Perhaps I'd leave one completed task like List.update to exemplify ideal formatting of a completed task.)

kili-ilo avatar Jan 27 '22 15:01 kili-ilo

@JanCVanB Yeah, go for it! 👍

rtfeldman avatar Jan 28 '22 02:01 rtfeldman

40+ down, 40+ to go! Thank you, everyone who implemented this first batch of new builtins 😃

Num

  • [x] toStr : Num * -> Str
  • [x] divFloor : Int a, Int a -> Int a
  • [x] divCeil : Int a, Int a -> Int a
  • [x] minI128 : I128

List

  • [x] last : List elem -> Result elem [ ListWasEmpty ]*
  • [x] max : List (Num a) -> Result (Num a) [ ListWasEmpty ]*
  • [x] min : List (Num a) -> Result (Num a) [ ListWasEmpty ]*
  • [x] #674
  • [x] product : List (Num a) -> Num a
  • [x] repeat : elem, Int -> List elem
  • [x] #2001
  • [x] range : Int a, Int a -> List (Int a)
  • [x] set : List elem, Int, elem -> List elem
  • [x] #1948
  • [x] dropLast : List elem -> List elem
  • [x] #1896
  • [x] drop : List elem, Int -> List elem
  • [x] takeFirst : List elem, Int -> List elem
  • [x] #1946
  • [x] #1985
  • [x] mapWithIndex : List before, (before, Int -> after) -> List after
  • [x] mapOks : List before, (before -> Result after *) -> List after
  • [x] #1887
  • [x] map2 : List a, List b, (a, b -> c) -> List c
  • [x] map3 : List a, List b, List c, (a, b, c -> d) -> List d
  • [x] #1837
  • [x] walkUntil : List elem, state, (state, elem -> [ Continue state, Stop state ]) -> state
  • [x] #1909
  • [x] #1928
  • [x] #1870
  • [x] sort : List elem, (elem, elem -> [ Lt, Eq, Gt ]) -> List elem
  • [x] #2383
  • [x] #2385
  • [x] swap : List elem, Nat, Nat -> List elem

Result

  • [x] default : Result ok *, ok -> ok
  • [x] map : Result before err, (before -> after) -> Result after err
  • [x] mapErr : Result ok before, (before -> after) -> Result ok after

Str

  • [x] fromUtf8 : List U8 -> Result Str [ BadUtf8 ]*
  • [x] trim : Str -> Str
  • [x] #1947

And @rvcas, thank you for the unlisted Str.to{Num *} builtins!

kili-ilo avatar Jan 28 '22 04:01 kili-ilo

Marking this as high prio given the increasing number of folks interested in using Roc joining.

ayazhafiz avatar Feb 15 '22 15:02 ayazhafiz

@rtfeldman It would be great if this list could be updated, since a lot of them have been implemented since June

snprajwal avatar Oct 18 '22 12:10 snprajwal

@snprajwal updated!

ayazhafiz avatar Oct 18 '22 13:10 ayazhafiz