Replacing stdin from within Haskell

Hi Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ? Why do I want this - well I'm using the pcap library and I want to uncompress data to feed into 'openOffile' (which will take "-" to designate read from stdin). Yes I can create a separate command and use the stuff in System.Process or uncompress it into a temporary file - but that all seems in-elegant. Suggestions? Cheers Neil

On Thu, Jun 9, 2011 at 13:40, Neil Davies
Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
If you don't mind being tied to GHC you can use hDuplicateTo from GHC.IO.Handle [1]. You can also use dupTo from the unix package [2], but that ties you to unix-like platforms instead. Erik [1] http://hackage.haskell.org/packages/archive/base/latest/doc/html/GHC-IO-Hand... [2] http://hackage.haskell.org/packages/archive/unix/latest/doc/html/System-Posi...

Quoth Erik Hesselink
On Thu, Jun 9, 2011 at 13:40, Neil Davies
wrote: Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
If you don't mind being tied to GHC you can use hDuplicateTo from GHC.IO.Handle [1]. You can also use dupTo from the unix package [2], but that ties you to unix-like platforms instead.
From reading about it, I would expect hDuplicate to to close and replace the input file descriptor for _all_ threads.
Processes are of course the elegant way to separate effects like this. Donn

On Thu, Jun 9, 2011 at 16:40, Donn Cave
Quoth Erik Hesselink
, On Thu, Jun 9, 2011 at 13:40, Neil Davies
wrote: Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
If you don't mind being tied to GHC you can use hDuplicateTo from GHC.IO.Handle [1]. You can also use dupTo from the unix package [2], but that ties you to unix-like platforms instead.
From reading about it, I would expect hDuplicate to to close and replace the input file descriptor for _all_ threads.
Processes are of course the elegant way to separate effects like this.
Ah yes, you are right. I've done this before, but that was after a double fork using 'forkProcess'. Erik

On 10/06/2011, at 1:11 AM, Erik Hesselink wrote:
On Thu, Jun 9, 2011 at 13:40, Neil Davies
wrote: Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
If you don't mind being tied to GHC you can use hDuplicateTo from GHC.IO.Handle [1]. You can also use dupTo from the unix package [2], but that ties you to unix-like platforms instead.
Erik
[1] http://hackage.haskell.org/packages/archive/base/latest/doc/html/GHC-IO-Hand...
That replaces stdin for *every* Haskell thread.
[2] http://hackage.haskell.org/packages/archive/unix/latest/doc/html/System-Posi...
That alters file descriptor 0 for *every* Haskell thread. As I understand the original poster's question, it would be paraphrased as "can the association between the default input stream used by getChar and the rest be changed for ONE thread in a Haskell program by some method that does NOT have any effect on any other thread in the same OS process". Or to put it another way, "do I really have to pass a handle around to all these functions in my thread?" And the answer would seem to be "there is no reason in principle why this *couldn't* be supported, but it *isn't*; there are no C-style thread-local global variables. Yes, you do have to pass that handle around more than you would like to."

On 10 June 2011 06:43, Richard O'Keefe
On 10/06/2011, at 1:11 AM, Erik Hesselink wrote:
Anyone out there got an elegant solution to being able to fork a haskell
On Thu, Jun 9, 2011 at 13:40, Neil Davies
wrote: thread and replace its 'stdin' ? If you don't mind being tied to GHC you can use hDuplicateTo from GHC.IO.Handle [1]. You can also use dupTo from the unix package [2], but that ties you to unix-like platforms instead.
Erik
[1] http://hackage.haskell.org/packages/archive/base/latest/doc/html/GHC-IO-Hand...
That replaces stdin for *every* Haskell thread.
[2] http://hackage.haskell.org/packages/archive/unix/latest/doc/html/System-Posi...
That alters file descriptor 0 for *every* Haskell thread.
As I understand the original poster's question, it would be paraphrased as "can the association between the default input stream used by getChar and the rest be changed for ONE thread in a Haskell program by some method that does NOT have any effect on any other thread in the same OS process". Or to put it another way, "do I really have to pass a handle around to all these functions in my thread?"
And the answer would seem to be "there is no reason in principle why this *couldn't* be supported, but it *isn't*; there are no C-style thread-local global variables. Yes, you do have to pass that handle around more than you would like to."
Could implicit parameters be used for this purpose? http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/other-type-extensions... Alexander

On Thu, Jun 9, 2011 at 07:40, Neil Davies
Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
File descriptors/file handles are per process, not per thread, on (almost?) every OS ghc supports. You'll need to create a full subprocess.

Thanks That is what I thought. I'll stick with what I'm doing at present which is to use temporary files - don't want to get into separate processes which I then have to co-ordinate. Cheers Neil On 9 Jun 2011, at 17:01, Brandon Allbery wrote:
On Thu, Jun 9, 2011 at 07:40, Neil Davies
wrote: Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
File descriptors/file handles are per process, not per thread, on (almost?) every OS ghc supports. You'll need to create a full subprocess.

On 9 Jun 2011, at 17:01, Brandon Allbery wrote:
On Thu, Jun 9, 2011 at 07:40, Neil Davies
wrote: Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
File descriptors/file handles are per process, not per thread, on (almost?) every OS ghc supports. You'll need to create a full subprocess.
There is actually a non-sequitur here. There is file descriptor 0, which is indeed per-process, and there is the thing that the Prelude functions like getChar read from. There is no law of logic, physics, or computation that says these have to be the same thing. There are plenty of programming languages (Pop, Ada, Prolog, and Common Lisp spring to mind, oh yes, and BCPL) where the default input stream can switched without affecting file descriptor 0 at all. For example, in Common Lisp, the default input stream is whatever is the value of the dynamic variable *STANDARD-INPUT*. I understood the OP's question to mean "does Haskell allow rebinding of what _it_ calls standard input", which would be YES for Pop, Ada, Prolog, and Lisp, just as it is NO for C.

On Thu, Jun 9, 2011 at 23:59, Richard O'Keefe
I understood the OP's question to mean "does Haskell allow rebinding of what _it_ calls standard input", which would be YES for Pop, Ada, Prolog, and Lisp, just as it is NO for C.
But none of those are Haskell, and neither GHC nor Hugs provides such an abstraction in the standard libraries. As I specifically tied my response to GHC, whose runtime I/O system does not allow such abstraction, my point stands. If the topic were Common Lisp, the answer would be different.

On 10/06/2011, at 4:12 PM, Brandon Allbery wrote:
On Thu, Jun 9, 2011 at 23:59, Richard O'Keefe
wrote: I understood the OP's question to mean "does Haskell allow rebinding of what _it_ calls standard input", which would be YES for Pop, Ada, Prolog, and Lisp, just as it is NO for C.
But none of those are Haskell, and neither GHC nor Hugs provides such an abstraction in the standard libraries.
The point is that they *could* have. The fact that they do not has nothing whatever to do with UNIX. It was a Haskell design decision. My point was not that Haskell can or should do this, but that answering "can I do this in Haskell" by pointing to what Unix does was no real explanation at all, given that other languages also running on Unix have no trouble rebinding "standard input", and that the OP's question was, even for someone thoroughly familiar with Unix, a reasonable question.

On Fri, Jun 10, 2011 at 00:36, Richard O'Keefe
The point is that they *could* have. The fact that they do not has nothing whatever to do with UNIX. It was a Haskell design decision.
I have this feeling you're looking at it backwards... The question was whether GHC could do this. My answer was based on "given the way GHC's I/O manager works, it would require the OS to support thread-independent file descriptors"; if I understand you correctly, this is an unacceptable approach, the only valid one being "given that OSes don't implement per-thread file handles, GHC is not designed to do this". So, why is that a privileged viewpoint?

On 11/06/2011, at 3:42 AM, Brandon Allbery wrote:
On Fri, Jun 10, 2011 at 00:36, Richard O'Keefe
wrote: The point is that they *could* have. The fact that they do not has nothing whatever to do with UNIX. It was a Haskell design decision.
I have this feeling you're looking at it backwards... The question was whether GHC could do this. My answer was based on "given the way GHC's I/O manager works, it would require the OS to support thread-independent file descriptors"; if I understand you correctly, this is an unacceptable approach, the only valid one being "given that OSes don't implement per-thread file handles, GHC is not designed to do this". So, why is that a privileged viewpoint?
No, you do not understand me correctly. Amongst other things, I said nothing about per-thread file handles. In fact, the whole point of what I said was that there is no *necessary* connection between operating system file handles and the things visible to Haskell source code whatever. Given that - a forkIO process can use Haskell file handles created in the parent process - the threads created by forkIO are not necessarily the same as operating system threads per-OS-thread file descriptors wouldn't be that much help anyway. Much about GHC has changed and will change. If anyone had seriously *wanted* GHC to support per-forkIO-thread standard-input and -output, it could have been designed to do that. It seems extremely odd to regard the current implementation as providing a "privileged viewpoint". Haskell threads are supposed to be lightweight cheap things that programmers can use without worrying about how big to make the stack (as in POSIX threads) or without worrying about running out of OS resources (like file descriptors) due to hidden resource allocation. The more ad hoc features get wired into Haskell threads, the harder it gets to implement them, the riskier it seems to use them, and the harder it gets to understand them. *This* is the privileged viewpoint: per-thread-stdin is not supported because nobody much *wants* it to be. There are other mechanisms (monad transformers, implicit parameters) for solving this problem.

On Thu, 9 Jun 2011, Neil Davies wrote:
Anyone out there got an elegant solution to being able to fork a haskell thread and replace its 'stdin' ?
Why do I want this - well I'm using the pcap library and I want to uncompress data to feed into 'openOffile' (which will take "-" to designate read from stdin). Yes I can create a separate command and use the stuff in System.Process or uncompress it into a temporary file - but that all seems in-elegant.
I think the clean solution is to have a parameter of type Handle, that the threads use for reading, instead of reading from stdin. Or pass the data from stdin in a lazy String.
participants (7)
-
Alexander Kjeldaas
-
Brandon Allbery
-
Donn Cave
-
Erik Hesselink
-
Henning Thielemann
-
Neil Davies
-
Richard O'Keefe