process icon indicating copy to clipboard operation
process copied to clipboard

Add `getArgs :: IO [OsString]`

Open tbidne opened this issue 9 months ago • 9 comments

With the Abstract FilePath Proposal, we can now provide functions that work on the more appropriate OsPath/OsString, rather than legacy type FilePath = [String]. In particular, we really ought to have a version for System.Environment.getArgs :: IO [String].

For example, see this optparse-applicative issue.

Unfortunately, OsString cannot reside in base, hence this function has to live somewhere else. As this function is related to the current process, how about in process?

Luckily implementation should be simple, since the Win32/Posix functions already exist, so all that remains is an OsString shim.

This issue is not for full OsString compatibility, though it is related. See also this discussion.

Thanks!

CC @hasufell

tbidne avatar Mar 23 '25 22:03 tbidne

@bgamari @tomjaguarpaw

hasufell avatar Mar 24 '25 00:03 hasufell

To connect the dots a bit, it seems that you're suggesting to add

getArgs :: IO [OsString]

It doesn't exactly fit what process is already about (which is launching and managing processes), but I don't have any strong objection to it being here. Still, since OsString is defined in filepath then why not there, close to the source?

tomjaguarpaw avatar Mar 25 '25 07:03 tomjaguarpaw

@tomjaguarpaw

I don't see what getArgs has to do with filepaths... the only thing it shares with filepath is a type (well... os-string, actually)... following that logic, I could re-implement the entirety of base/the ecosystem in filepath. That doesn't seem right.

Additionally, I want to keep filepath as low in IO functionality as possible. It's supposed to deal with filepaths, not with operating system API.

The place it was suggested to be implemented in was file-io: https://github.com/haskell/file-io/issues/41 But file-io is supposed to just deal with file operations. getArgs isn't one of them.

Process spawning is definitely related to process arguments:

  • https://pubs.opengroup.org/onlinepubs/007904975/functions/posix_spawn.html
  • https://hackage.haskell.org/package/process-1.6.25.0/docs/System-Process.html#t:CmdSpec
  • https://hackage.haskell.org/package/process-1.6.25.0/docs/System-Process.html#v:callProcess

hasufell avatar Mar 25 '25 07:03 hasufell

For non-OsString, process could simply re-export getArgs from base.

hasufell avatar Mar 25 '25 08:03 hasufell

I have no objection to including it here.

tomjaguarpaw avatar Mar 25 '25 08:03 tomjaguarpaw

I'm thinking a new module, perhaps, e.g.:

  • System.Process.Env and
  • System.Process.Env.OsString

hasufell avatar Mar 25 '25 08:03 hasufell

I don't much care where getArgs :: IO [OsString] lives either, but it must exist somewhere other than base. The question is where?

filepath (or file-io) are tempting, since the types already exist there. But the functionality itself -- obtaining the current process's args -- is completely irrelevant to the rest of the package, so it's an awkward fit, and it doesn't scale either, since there are plenty of other FilePath functions deserving of the same treatment.

Gabriella Gonzalez's post on vertical vs. horizontal module organization is relevant here. The "vertical" approach would put getArgs :: IO [OsString] in the package with the most closely related functionality. Of boot packages, that is process, imo.

The alternative would be creating a new package e.g. os-string-environment. I don't relish this as I don't think it scales well either (do we have to create a new package for each "OsString functionality" that would otherwise exist in base?). But it is an option.

tbidne avatar Mar 26 '25 00:03 tbidne

~~If it helps, here is an example of what the implementation might look like.~~

Edit: PR: https://github.com/haskell/process/pull/339

tbidne avatar Mar 27 '25 00:03 tbidne

Why not just open a PR?

hasufell avatar Mar 27 '25 00:03 hasufell