openTempFile only defined on GHC

Hi,
From the System.IO export list:
#ifdef __GLASGOW_HASKELL__ openTempFile, openBinaryTempFile, #endif So we have a standardised module with a standardised interface which is totally broken on all but one compiler. Can this please be either: 1) Implemented for all compilers 2) Removed, and then potentially re-added by the proper libraries submission process I hope the new libraries submission process will stop things like this being added in future, without appropriate thought. Thanks Neil

Neil Mitchell wrote:
Hi,
From the System.IO export list:
#ifdef __GLASGOW_HASKELL__ openTempFile, openBinaryTempFile, #endif
So we have a standardised module with a standardised interface which is totally broken on all but one compiler.
Can this please be either:
1) Implemented for all compilers 2) Removed, and then potentially re-added by the proper libraries submission process
I hope the new libraries submission process will stop things like this being added in future, without appropriate thought.
Isn't it just a bug that these functions are not implemented by other compilers? There's no fundamental reason, right? The implementation is necessarily dependent on the internals of Handle because openFile doesn't currently provide a way to open a file and fail if it already exists (the O_EXCL flag). Cheers, Simon

Hello Simon, Monday, April 2, 2007, 2:16:55 PM, you wrote:
openTempFile, openBinaryTempFile,
Isn't it just a bug that these functions are not implemented by other compilers? There's no fundamental reason, right? The implementation is necessarily dependent on the internals of Handle because openFile doesn't currently provide a way to open a file and fail if it already exists (the O_EXCL flag).
this means that these functions should be implemented in GHC.*, NHC.* and Hugs.* and only then System.IO may include interface function that will call one of them -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Monday 02 April 2007 12:48, Bulat Ziganshin wrote:
this means that these functions should be implemented in GHC.*, NHC.* and Hugs.* and only then System.IO may include interface function that will call one of them
I don't think that this will really solve portability issues, as we would still need #ifdefs in System.IO to import the right module. The general question is: Where do we want to solve these issues: Within the code or outside of it (i.e. in the build system)? Both approaches have pros and cons, but if we want to factor things out into the build system, we would need a System.IO.Impl module, which is specific to a Haskell implementation and outside base, but which has an implementation-independent API. Mixing both approaches only complicates things with no real benefit. Cheers, S.

Hello Sven, Monday, April 2, 2007, 4:21:47 PM, you wrote:
this means that these functions should be implemented in GHC.*, NHC.* and Hugs.* and only then System.IO may include interface function that will call one of them
I don't think that this will really solve portability issues, as we would still need #ifdefs in System.IO to import the right module.
yes, and this is standard practice. modules in base package should have compiler-independent interface, but not implementation
The general question is: Where do we want to solve these issues: Within the code or outside of it (i.e. in the build system)? Both approaches have pros and cons, but if we want to factor things out into the build system, we would need a System.IO.Impl module, which is specific to a Haskell implementation and outside base, but which has an implementation-independent API. Mixing both approaches only complicates things with no real benefit.
afaiu, this is not relevant in light of my remark? -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Monday 02 April 2007 14:41, Bulat Ziganshin wrote:
Hello Sven,
Monday, April 2, 2007, 4:21:47 PM, you wrote:
this means that these functions should be implemented in GHC.*, NHC.* and Hugs.* and only then System.IO may include interface function that will call one of them
I don't think that this will really solve portability issues, as we would still need #ifdefs in System.IO to import the right module.
yes, and this is standard practice. modules in base package should have compiler-independent interface, but not implementation
"standard" does not necessarily imply "good".
The general question is: Where do we want to solve these issues: Within the code or outside of it (i.e. in the build system)? Both approaches have pros and cons, but if we want to factor things out into the build system, we would need a System.IO.Impl module, which is specific to a Haskell implementation and outside base, but which has an implementation-independent API. Mixing both approaches only complicates things with no real benefit.
afaiu, this is not relevant in light of my remark?
It is relevant: Before joyfully moving things around modules, we should have a common and clear picture what we should aim for. Currently, I don't see this, so I object to ad hoc changes. Cheers, S.

Simon Marlow
Isn't it just a bug that these functions are not implemented by other compilers?
Yes and no. Of course we could implement them. But I for one wasn't even aware that they existed in the API. I don't know when they were added, or by whom, and I may not even be sure what they are supposed to do. For instance, you mention not opening a file if it already exists, but the Haddock does not say anything about that. Regards, Malcolm

Malcolm Wallace wrote:
Simon Marlow
wrote: Isn't it just a bug that these functions are not implemented by other compilers?
Yes and no. Of course we could implement them. But I for one wasn't even aware that they existed in the API. I don't know when they were added, or by whom, and I may not even be sure what they are supposed to do. For instance, you mention not opening a file if it already exists, but the Haddock does not say anything about that.
They were added in Jan 2005 by Krasimir: Thu Jan 6 19:35:07 GMT 2005 krasimir * [project @ 2005-01-06 19:35:05 by krasimir] add temporary files API I agree the documentation is lacking and should be improved. The reason they were added to System.IO, I suspect is because the alternative is worse: System.IO.Extras, GHC.IO.Extras or something else. Apart from being uninformative names, there's nothing compiler-dependent about these functions, and our naming guidelines forbid module names that don't have anything to do with functionality. The intention was that the missing implementations would appear in due course. Perhaps as a first step, rather than just omitting them from the export list where they aren't supported, they should be replaced by dummy definitions that emit a helpful error message? I suspect there are many such examples in the base package, FWIW. nch98 doesn't implement various bits of System.IO.Error, for example. Hugs has a very different version of Control.Concurrent. Cheers, Simon

Hi
Perhaps as a first step, rather than just omitting them from the export list where they aren't supported, they should be replaced by dummy definitions that emit a helpful error message?
Like canonicalizeFilePath, which has a dummy implementation everywhere? It's frustrating to have a standard base library which isn't standard and portable. I realise that the reason that this was added was for race-free temporary file creation, but until they are available on Hugs, my code will use a race-full implementation everywhere, including GHC. Could we perhaps have an implementation of this function for all other compilers: -- Note: openTempFile is not available on Hugs, which sucks openTempFileLocal :: FilePath -> String -> IO (FilePath, Handle) openTempFileLocal dir template = do i <- randomRIO (1000::Int,9999) let (file,ext) = splitExtension template s = dir > (file ++ show i) <.> ext b <- doesFileExist s if b then openTempFileLocal dir template else do h <- openFile s ReadWriteMode return (s, h) That's what I use everywhere.
I suspect there are many such examples in the base package, FWIW. nch98 doesn't implement various bits of System.IO.Error, for example. Hugs has a very different version of Control.Concurrent.
I think these should be made very explicit in the documentation. Control.Concurrent is understandable, things like file creation methods aren't - a user will be annoyed (and I was) to find that their program written according to the documentation doesn't work. Thanks Neil

Neil Mitchell wrote:
Hi
Perhaps as a first step, rather than just omitting them from the export list where they aren't supported, they should be replaced by dummy definitions that emit a helpful error message?
Like canonicalizeFilePath, which has a dummy implementation everywhere? It's frustrating to have a standard base library which isn't standard and portable. I realise that the reason that this was added was for race-free temporary file creation, but until they are available on Hugs, my code will use a race-full implementation everywhere, including GHC.
Could we perhaps have an implementation of this function for all other compilers:
-- Note: openTempFile is not available on Hugs, which sucks openTempFileLocal :: FilePath -> String -> IO (FilePath, Handle) openTempFileLocal dir template = do i <- randomRIO (1000::Int,9999) let (file,ext) = splitExtension template s = dir > (file ++ show i) <.> ext b <- doesFileExist s if b then openTempFileLocal dir template else do h <- openFile s ReadWriteMode return (s, h)
That's what I use everywhere.
What does the "local" in openTempFileLocal mean? I'd be perfectly happy to have non-race-free implementations of openTempFile for certain compilers/platforms as long as we document it (not that we document openTempFile properly at all at the moment, which is a bug). Also note that you can't use > or <.> here, because filepath is not in base :-)
I suspect there are many such examples in the base package, FWIW. nch98 doesn't implement various bits of System.IO.Error, for example. Hugs has a very different version of Control.Concurrent.
I think these should be made very explicit in the documentation. Control.Concurrent is understandable, things like file creation methods aren't - a user will be annoyed (and I was) to find that their program written according to the documentation doesn't work.
I quite agree. Care to send a patch, or open a ticket? Cheers, Simon

Hi
What does the "local" in openTempFileLocal mean?
Do not conflict with the name openTempFile - a copy local to this project - no real meaning on the implementation of the function.
I'd be perfectly happy to have non-race-free implementations of openTempFile for certain compilers/platforms as long as we document it (not that we document openTempFile properly at all at the moment, which is a bug).
Yes, that's probably the way to go.
Also note that you can't use > or <.> here, because filepath is not in base :-)
Boo! :-)
I think these should be made very explicit in the documentation. Control.Concurrent is understandable, things like file creation methods aren't - a user will be annoyed (and I was) to find that their program written according to the documentation doesn't work.
I quite agree. Care to send a patch, or open a ticket?
Yeah, I will try and do this today. Thanks Neil
participants (5)
-
Bulat Ziganshin
-
Malcolm Wallace
-
Neil Mitchell
-
Simon Marlow
-
Sven Panne