Stream: API design

Topic: File and Path


view this post on Zulip Richard Feldman (Jan 02 2024 at 19:55):

I just realized there's a simple and nice solution to a longstanding annoyance: functions like File.readUtf8 take a Path, which means in order to call them with a string you always have to do Path.fromStr on that string first

view this post on Zulip Richard Feldman (Jan 02 2024 at 19:56):

it's important to have those operations available on Paths, because you can get a Path from things like Dir.list and paths aren't necessarily valid strings (e.g. on UNIX, path can be any sequence of nonzero bytes, which is very much not necessarily valid UTF-8!)

view this post on Zulip Richard Feldman (Jan 02 2024 at 19:57):

but I just realized that we can do this to make the experience nicer:

view this post on Zulip Richard Feldman (Jan 02 2024 at 19:58):

now you have easy access to functions that take a Str for convenience, and also if you have a Path you can also easily call functions on those too using the Path module!

view this post on Zulip Richard Feldman (Jan 02 2024 at 19:59):

curious what others think (cc @Luke Boswell)

view this post on Zulip Fabian Schmalzried (Jan 02 2024 at 21:13):

I think this would be helpful. But it could be confusing, to have two functions doing the same, so an explanation somewhere in the docs would be good.

view this post on Zulip Richard Feldman (Jan 02 2024 at 21:32):

yeah, I think each of the functions could have a line at the end of its doc comment which notes its relationship to the one in the other module, and linking to that other one

view this post on Zulip Luke Boswell (Jan 02 2024 at 23:28):

I don't really follow the proposal here, specifically the following is confusing me.

Duplicate those back into File except they take Str as their first argument as Path, and now they're just convenience wrappers which do the Path.fromStr for you

Does this mean we would have the following? Why can't we just do this anyway and add another error tag for invalid path?

# uses a Str instead of a Path here?
File.writeBytes : Str, List U8 -> Task {} [FileWriteErr Path WriteErr]

view this post on Zulip Richard Feldman (Jan 02 2024 at 23:31):

oh sorry - so I'm saying we have these two:

File.writeBytes : Str, List U8 -> Task {} [FileWriteErr Path WriteErr]
Path.writeBytes : Path, List U8 -> Task {} [FileWriteErr Path WriteErr]

so they're exactly the same except for the first argument

view this post on Zulip Richard Feldman (Jan 02 2024 at 23:33):

including error type and everything

view this post on Zulip Luke Boswell (Jan 02 2024 at 23:48):

I'm still thinking about this... but one question this makes we think of; would it be possible to use an Ability here as the argument instead of Path? Like maybe anything that is toStrable could be used??

view this post on Zulip Brendan Hansknecht (Jan 02 2024 at 23:50):

You could make a toPath ability that is on path, str, and list U8 theoretically.

view this post on Zulip Brendan Hansknecht (Jan 02 2024 at 23:51):

But roc doesn't let you add an new ability to a builtin. So it doesn't really work

view this post on Zulip Luke Boswell (Jan 02 2024 at 23:52):

Brendan Hansknecht said:

But roc doesn't let you add an new ability to a builtin. So it doesn't really work

Is this a deliberate design decision? Is this so the dependencies are only one way and there are no cycles?

view this post on Zulip Brendan Hansknecht (Jan 02 2024 at 23:55):

I think deliberate design to keep abilities simple/low in power, but not really sure

view this post on Zulip Richard Feldman (Jan 03 2024 at 01:08):

we actually talked about this explicit question at some point on Zulip a long time ago, I forget where

view this post on Zulip Richard Feldman (Jan 03 2024 at 01:09):

the way to do it would be something more like making a FromStr builtin ability that opaque types could opt into

view this post on Zulip Richard Feldman (Jan 03 2024 at 01:09):

but the thing is, this is literally the only demand we've ever had for it, so I think it's better to go with a simpler solution for now

view this post on Zulip Richard Feldman (Jan 03 2024 at 01:09):

maybe if we accumulate a bunch of cases where it would be useful we could revisit that

view this post on Zulip Richard Feldman (Jan 03 2024 at 01:09):

but I think for now it's best to do something that works today and see how that feels

view this post on Zulip Brendan Hansknecht (Jan 03 2024 at 02:41):

FromStr wouldn't work here. You want path to be generatable from a Str or a List U8

view this post on Zulip Brendan Hansknecht (Jan 03 2024 at 02:41):

Cause a path doesn't need to be utf8

view this post on Zulip Brendan Hansknecht (Jan 03 2024 at 02:42):

So I don't think there is a way to make a generic ability for this currently

view this post on Zulip Brendan Hansknecht (Jan 03 2024 at 02:44):

Today you need either multiple separate functions or a tag


Last updated: Jul 06 2025 at 12:14 UTC