Not at all. See the documentation of System.OsPath
Basically, the point of OsString
is to just keep whatever OS API (e.g. syscalls) throws back at you without any data transformation. That is what you then want for getArgs
.
See the unix package:
getArgs :: IO [PosixString]
getArgs =
alloca $ \ p_argc ->
alloca $ \ p_argv -> do
getProgArgv p_argc p_argv
p <- fromIntegral <$> peek p_argc
argv <- peek p_argv
peekArray (p - 1) (advancePtr argv 1) >>= mapM (fmap PS . B.packCString)
Compare that with base:
getArgs :: IO [String]
getArgs =
alloca $ \ p_argc ->
alloca $ \ p_argv -> do
getProgArgv p_argc p_argv
p <- fromIntegral `liftM` peek p_argc
argv <- peek p_argv
enc <- argvEncoding
peekArray (p - 1) (advancePtr argv 1) >>= mapM (GHC.peekCString enc)
GHC.peekCString
here is what causes the disaster, while B.packCString
does not to do any decoding.
You might notice that we have PosixString
here (oh no, yet another type…). That’s because this allows us to express “posix strings” and “windows strings”, while OsString
means “string of the current platform”.
E.g. for tar
, we actually need PosixString
, even if we’re on windows. All this has panned out nicely so far.
Are they the same as ByteString
? No. They’re rather wrappers around ShortByteString
(which is unpinned memory).
Again: there are differences, both in properties and implementation, between string types.