RE: [Haskell-cafe] Project postmortem
On 02 December 2005 12:11, Tomasz Zielonka wrote: On Fri, Dec 02, 2005 at 11:20:54AM -, Simon Marlow wrote: If anyone is interested, this turned out to be a bug in the Network.BSD module, namely that getHostByName isn't thread safe because it is based on the C library function gethostbyname(), which returns data in a single static area. Workarounds are: - do your own mutual exclusion locking around getHostByName and any function that calls it (eg. connectTo). - use Network.Alt (http://www.cs.helsinki.fi/u/ekarttun/network-alt/), which has a thread-safe implementation of getHostByName. - wait for 6.4.2, which will contain a fix for this bug (we don't have a fix committed yet, Einar Karttunen has kindly offered to look into it). Do I understand correctly that another workaround is - don't compile your programs with -threaded ? No, the bug isn't related to -threaded. It still occurs without -threaded. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Project postmortem
On Fri, Dec 02, 2005 at 12:39:25PM -, Simon Marlow wrote: Do I understand correctly that another workaround is - don't compile your programs with -threaded ? No, the bug isn't related to -threaded. It still occurs without -threaded. Let's check that now I understand - so the sequence call gethostbyname read the returned hostent is written in Haskell, and many such sequences can be interleaved when using Concurrent Haskell? Best regards Tomasz -- I am searching for a programmer who is good at least in some of [Haskell, ML, C++, Linux, FreeBSD, math] for work in Warsaw, Poland ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Project postmortem
On 02 December 2005 12:49, Tomasz Zielonka wrote: On Fri, Dec 02, 2005 at 12:39:25PM -, Simon Marlow wrote: Do I understand correctly that another workaround is - don't compile your programs with -threaded ? No, the bug isn't related to -threaded. It still occurs without -threaded. Let's check that now I understand - so the sequence call gethostbyname read the returned hostent is written in Haskell, and many such sequences can be interleaved when using Concurrent Haskell? Yes, exactly. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Project postmortem
On 02 December 2005 12:25, Joel Reymont wrote: I thought that if -threaded is not used then all the blocking IO is assigned a separate OS thread. No - the runtime is completely single-threaded without -threaded. Blocking I/O is managed by the runtime. With -threaded, blocking I/O is managed by a Haskell thread. The programmer shouldn't see any difference in the behaviour of I/O. Is the documentation for -threaded lacking? I realise it's a bit terse, but do you have any concrete suggestions for improving it? Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Threaded runtime (was Re: [Haskell-cafe] Project postmortem)
Simon, On Dec 2, 2005, at 1:16 PM, Simon Marlow wrote: No - the runtime is completely single-threaded without -threaded. Blocking I/O is managed by the runtime. With -threaded, blocking I/ O is managed by a Haskell thread. The programmer shouldn't see any difference in the behaviour of I/O. I was going on this quote by Simon PJ: -- It should be find to have lots of threads, esp if most of them are asleep. The only thing to watch out for is that GHC's runtime system will consume one *OS* thread for each *blocked* foreign call. So if you have 10k threads each making a separate call to the OS to read from 10k sockets, and they all block, you'll use 10k OS threads, and that will probably fail. -- Is this correct and if so how does it mesh with what you said above? Is the documentation for -threaded lacking? I realise it's a bit terse, but do you have any concrete suggestions for improving it? Not at the moment but I'll think about it once I understand everything. It could be worth summarizing every clarification in this thread. Thanks, Joel -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: wxHaskell and do statements
Am Dienstag, 29. November 2005 16:16 schrieb Sebastian Sylvan: IIRC Haskell assumes a tab is 8 spaces. Correctly, it is explicitly specified in the Haskell spec, see: http://haskell.org/onlinereport/syntax-iso.html#layout IMO that's way too much. Haskell tends to take up quite a bit of horizontal real-estate so I usually go with 2 spaces. At any rate, I set my editor to convert them to spaces. I think this in general the best idea for all projects, even if the language in question has no layout rule. Tabs are simply evil... Cheers, S. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Examining the Haskell stack (read at your own risk ; -))
Simon, You told me a bit about how to examine the Haskell stack by looking at R22 on the PowerPC and $ebx on Intel architectures. I looked at your .gdbinit but could not figure out which macros are to be used. The example below is a bit contrived in that I'm freeing the SSL context twice, on purpose. I tried getting a disassembler dump using the contents of R22 without luck: (gdb) info registers r22 r220x137a3cc20423628 (gdb) disas 0x137a3cc No function contains specified address. This is my stack trace: Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x0019 0x00568fe0 in sk_pop_free () (gdb) where #0 0x00568fe0 in sk_pop_free () #1 0x0059f128 in X509_VERIFY_PARAM_free () #2 0x003c4d5c in SSL_free () #3 0x000c3254 in r7cH_info () #4 0x000ccd04 in schedule (mainThread=0x13f3f18, initialCapability=0x578df0) at Schedule.c:932 #5 0x000cdcac in waitThread_ (m=0x1100360, initialCapability=0x0) at Schedule.c:2156 #6 0x000cdb90 in scheduleWaitThread (tso=0x13c, ret=0x0, initialCapability=0x0) at Schedule.c:2050 #7 0x0001ff0c in rts_evalLazyIO (p=0x1ce0c8, ret=0x0) at RtsAPI.c:459 #8 0x495c in main (argc=25, argv=0x578df0) at Main.c:104 (gdb) info registers r22 r220x137a3cc20423628 (gdb) disas 0x137a3cc No function contains specified address. -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] RE: Examining the Haskell stack (read at your own risk ; -))
On 02 December 2005 14:03, Joel Reymont wrote: You told me a bit about how to examine the Haskell stack by looking at R22 on the PowerPC and $ebx on Intel architectures. I looked at your .gdbinit but could not figure out which macros are to be used. The example below is a bit contrived in that I'm freeing the SSL context twice, on purpose. I tried getting a disassembler dump using the contents of R22 without luck: (gdb) info registers r22 r220x137a3cc20423628 (gdb) disas 0x137a3cc No function contains specified address. This is my stack trace: Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x0019 0x00568fe0 in sk_pop_free () (gdb) where #0 0x00568fe0 in sk_pop_free () #1 0x0059f128 in X509_VERIFY_PARAM_free () #2 0x003c4d5c in SSL_free () #3 0x000c3254 in r7cH_info () #4 0x000ccd04 in schedule (mainThread=0x13f3f18, initialCapability=0x578df0) at Schedule.c:932 #5 0x000cdcac in waitThread_ (m=0x1100360, initialCapability=0x0) at Schedule.c:2156 #6 0x000cdb90 in scheduleWaitThread (tso=0x13c, ret=0x0, initialCapability=0x0) at Schedule.c:2050 #7 0x0001ff0c in rts_evalLazyIO (p=0x1ce0c8, ret=0x0) at RtsAPI.c:459 #8 0x495c in main (argc=25, argv=0x578df0) at Main.c:104 (gdb) info registers r22 r220x137a3cc20423628 (gdb) disas 0x137a3cc No function contains specified address. It looks like your crash happened in the SSL library, and you have a useful stack trace there. r22 is a pointer to the stack, not a pointer to code, so you can't disassemble it, you need to display memory (as I described in separate mail). Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: Threaded runtime (was Re: [Haskell-cafe] Project postmortem)
On 02 December 2005 13:32, Joel Reymont wrote: I was going on this quote by Simon PJ: -- It should be find to have lots of threads, esp if most of them are asleep. The only thing to watch out for is that GHC's runtime system will consume one *OS* thread for each *blocked* foreign call. So if you have 10k threads each making a separate call to the OS to read from 10k sockets, and they all block, you'll use 10k OS threads, and that will probably fail. -- Is this correct and if so how does it mesh with what you said above? It's correct, but not the whole story. When you do a blocking I/O operation, it is not implemented in terms of a blocking foreign call, so it doesn't create an OS thread(*). In -threaded mode, blocking I/O is implemented by sending a reguest to the I/O manager thread, which returns a response when I/O is available. In non-threaded mode, blocking I/O is implemented by returning to the runtime, which occasionally checks for available I/O and wakes up the appropraite threads. Either way, as I said, the programmer doesn't see any difference. (*) except on Windows, where everything is done differently and blocking I/O currently gets a real OS thread. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Examining the Haskell stack (read at your own risk ; -))
On Dec 2, 2005, at 2:08 PM, Simon Marlow wrote: It looks like your crash happened in the SSL library, and you have a useful stack trace there. This is contrived in that I already know where the error is and it clearly points to SSL_free. I'm trying to figure out how I would have gotten to that call to getHostByName. r22 is a pointer to the stack, not a pointer to code, so you can't disassemble it, you need to display memory (as I described in separate mail). Quoting you: --- gdb p16 $r22 which prints 16 words of memory backwards (the way I like it) starting at the addresss in $r22. when displaying memory this way, gdb very handily prints the symbol name for words that point into the program. You can then pick things off the stack that look like return addresses and disassemble them, if you want. --- And p16 is defined in .gdbinit as: define p16 pmem $arg0 16 end Printing the 16 words gives me the printout below but where do I find my Haskell function? The code tha causes the crash looks like this: maybeFreeSSL :: MaybeSSL - IO () maybeFreeSSL tmv = do putStrLn $ maybeFreeSSL invoked mssl - atomically $ swapTMVar tmv Nothing case mssl of Nothing - return () Just (ssl, _, _) - do sslFree ssl sslFree ssl Is there a way to have maybeFreeSSL in the trace? I compiled the app with -debug but the libraries and the above maybeFreeSSL code was compiled without it. Thanks, Joel P.S. Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x0019 0x00568fe0 in sk_pop_free () (gdb) p16 $r22 0x137a40c: 0x1ce63c stg_NO_TREC_closure 0x137a408: 0x0 0x137a404: 0x0 0x137a400: 0x18fd0 stg_TREC_HEADER_info 0x137a3fc: 0xd6dbc stg_stop_thread_info 0x137a3f8: 0xd6f38 stg_noforceIO_info 0x137a3f4: 0x13ef148 0x137a3f0: 0x0 0x137a3ec: 0x2605c stg_catch_frame_info 0x137a3e8: 0x25c80 stg_unblockAsyncExceptionszh_ret_info 0x137a3e4: 0x13ef150 0x137a3e0: 0x27030 s3BN_info 0x137a3dc: 0x1d22cc GHCziConc_lvl7_closure 0x137a3d8: 0x26f6c s3BK_info 0x137a3d4: 0x13f38f4 0x137a3d0: 0x243f4 s7Fy_info 0x137a3cc: 0xc3270 s7FI_info -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] RE: Examining the Haskell stack (read at your own risk ; -))
On 02 December 2005 14:17, Joel Reymont wrote: On Dec 2, 2005, at 2:08 PM, Simon Marlow wrote: It looks like your crash happened in the SSL library, and you have a useful stack trace there. This is contrived in that I already know where the error is and it clearly points to SSL_free. I'm trying to figure out how I would have gotten to that call to getHostByName. r22 is a pointer to the stack, not a pointer to code, so you can't disassemble it, you need to display memory (as I described in separate mail). Quoting you: --- gdb p16 $r22 which prints 16 words of memory backwards (the way I like it) starting at the addresss in $r22. when displaying memory this way, gdb very handily prints the symbol name for words that point into the program. You can then pick things off the stack that look like return addresses and disassemble them, if you want. --- And p16 is defined in .gdbinit as: define p16 pmem $arg0 16 end Printing the 16 words gives me the printout below but where do I find my Haskell function? The code tha causes the crash looks like this: maybeFreeSSL :: MaybeSSL - IO () maybeFreeSSL tmv = do putStrLn $ maybeFreeSSL invoked mssl - atomically $ swapTMVar tmv Nothing case mssl of Nothing - return () Just (ssl, _, _) - do sslFree ssl sslFree ssl Is there a way to have maybeFreeSSL in the trace? I compiled the app with -debug but the libraries and the above maybeFreeSSL code was compiled without it. Thanks, Joel P.S. Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x0019 0x00568fe0 in sk_pop_free () (gdb) p16 $r22 0x137a40c: 0x1ce63c stg_NO_TREC_closure 0x137a408: 0x0 0x137a404: 0x0 0x137a400: 0x18fd0 stg_TREC_HEADER_info 0x137a3fc: 0xd6dbc stg_stop_thread_info 0x137a3f8: 0xd6f38 stg_noforceIO_info 0x137a3f4: 0x13ef148 0x137a3f0: 0x0 0x137a3ec: 0x2605c stg_catch_frame_info 0x137a3e8: 0x25c80 stg_unblockAsyncExceptionszh_ret_info 0x137a3e4: 0x13ef150 0x137a3e0: 0x27030 s3BN_info 0x137a3dc: 0x1d22cc GHCziConc_lvl7_closure 0x137a3d8: 0x26f6c s3BK_info 0x137a3d4: 0x13f38f4 0x137a3d0: 0x243f4 s7Fy_info 0x137a3cc: 0xc3270 s7FI_info Ok, you want a crash course in reading the Haskell stack. Each xxx_info symbol is a return address. The other values are the contents of stack frames: values saved for use at the return address. A return address also has an associated info table (use pinfo in the .gdbinit I sent you for disaplying the info table, eg. pinfo s7FI_info). Understanding info tables is beyond the scope of this message; please see InfoTables.h in the GHC sources. You probably want to know what each return address corresponds to: - the ones beginning stg_ are in the runtime, you can see the code for these in the GHC sources (grep in ghc/rts). - the ones that look like s7FI_info are local symbols. You might be able to find which module it comes from by grepping the .o files in your program and the .a library files. If you find it in a library, you can use 'nm' on the library to get a better idea of what function the symbol is associated with. One problem is that because these are local symbols, you might find the same symbol in multiple places, and you have to make an educated guess as to which is the appropriate one (or use the disassembly to distinguish). To map this back to Haskell code, you need to recompile the original module and dump the intermediate code with -ddump-stg. Understanding the output of -ddump-stg is beyond the scope of this message :-) Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: returning lists
raptor [EMAIL PROTECTED] writes, ]- that is the problem :), 'cause such functions should accept Char and String, but return a Tuple of Strings, but it is recursive (so that it fetch next,next,next char :)) i.e. it is own consumer and should return String --this is wrong, just tring grab char (x:xs) You might also have a look at http://haskell.org/hawiki/WorkerWrapper This idea should apply here. -Chad Scherrer ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Examining the Haskell stack (read at your own risk ; -))
Thank you Simon! This is very helpful and will take me a while to digest. On Dec 2, 2005, at 2:43 PM, Simon Marlow wrote: Ok, you want a crash course in reading the Haskell stack. Each xxx_info symbol is a return address. The other values are the contents of stack frames: values saved for use at the return address. -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] STM, Concurrent Haskell and network clients (long, code)
Folks, After two months with Haskell I think I'm starting to get the proper spirit. Inspired by Simon PJ's recent comments about lots of threads not hurting Haskell I introduced STM into my network client. I would like to run my architecture by you to see if there are any improvements to be made. I would like the code to be as bullet-proof as possible. I'm also jumping through some hoops to make sure none of the 3 threads (main, socket reader and socket writer) block indefinitely. I'm getting a thread blocked indefinitely exception now and I think this is because the main thread is not getting notified when the socket threads die. My network client has two threads. #1 reads network packets, converts them to events and posts them to a TChan using a function passed to it by the main thread. #2 blocks on a second TChan and waits for events to be sent out through the socket. The main thread creates a TChan to read events from, passes a closure that writes to the TChan to the network client and uses a network client function to send events to the network client. All in all it works out very nicely as there's no networking, FFI, etc. in the network client logic. This is an improvement from what I had before. The function that starts the poker client has this signature: startPokerClient :: (Event - IO ()) -- fun to send events to the main thread - HostInfo -- (host, port) - AuthInfo -- (user, pass, etc.) - IO PokerClient where data PokerClient = PC !MaybeThread !MaybeThread !(TChan Command) The main network client thread calls this fun to deliver events to the network client: writePokerClient :: PokerClient - Command - IO () writePokerClient (PC _ _ chan) cmd = atomically $ writeTChan chan cmd Main thread can stop the network client using stopPokerClient :: PokerClient - IO () stopPokerClient (PC tmv2 tmv1 _) = do putStrLn $ stopPokerClient invoked maybeKillThread tmv2 maybeKillThread tmv1 The abbreviated startPokerClient looks like this.. {-# NOINLINE lock #-} lock :: MVar () lock = unsafePerformIO $ newMVar () startPokerClient post (host, port) auth = do h - withMVar lock -- getHostByName is not thread-safe $ \_ - connectTo host (PortNumber $ fromIntegral port) `catchError` (\e - fail $ Failed to connect to server: ++ show e) -- kick off the SSL handshake ssl - startSSL doSSLHandshake h ssl ... -- we need one thread to always kill the other (tmv1 :: MaybeThread) - atomically $ newEmptyTMVar (tmv2 :: MaybeThread) - atomically $ newEmptyTMVar (tmvssl :: MaybeSSL) - atomically $ newTMVar (Just ssl) -- thread to read from the socket and post commands tid1 - forkIO $ writeLoop post h ssl `finally` finalize tmv1 tmv2 h tmvssl post -- thread to write to grab commands generated -- by the main thread and write them to the socket chan - atomically $ newTChan tid2 - forkIO $ readLoop h chan `finally` finalize tmv2 tmv1 h tmvssl post -- we have both threads now atomically $! do putTMVar tmv1 (Just tid1) putTMVar tmv2 (Just tid2) return $! PC tmv2 tmv1 chan Interestingly enough, I had to use $! otherwise startPokerClient was sitting there for a while, due to due to lazy evaluation I assume. I'm using the following finalizer for my socket reader/writer threads to make sure that if one thread dies the other one is taken with it and that the main thread is notified. I don't have a Maybe around the socket itself since I don't think closing a socket twice has any bad side effects. I put it in a try, though, for good measure. finalize :: MaybeThread - MaybeThread - Handle - MaybeSSL - (Event - IO ()) - IO () finalize me buddy h ssl post = do -- make sure we are not killed again -- killing a dead thread is apparently -- not free of side effects in GHC 6.4.1 atomically $ putTMVar me Nothing -- kill the other thread maybeKillThread buddy maybeFreeSSL ssl try $ hClose h post $ StopScript -- notify main thread return () The rest of the relevant code is below. Please let me know if it can be simplified or made more robust. maybeFreeSSL :: MaybeSSL - IO () maybeFreeSSL tmv = do putStrLn $ maybeFreeSSL invoked mssl - atomically $ swapTMVar tmv Nothing case mssl of Nothing - return () Just (ssl, _, _) - do sslFree ssl sslFree ssl maybeKillThread :: MaybeThread - IO () maybeKillThread tmv = do putStrLn $ maybeKillThread invoked mtid - atomically $ swapTMVar tmv Nothing case mtid of Nothing - return () Just tid
[Haskell-cafe] Thread blocked indefinitely
Folks, I'm trying to learn more about this exception. Would someone with a subscription to ACM kindly send me this paper: http://portal.acm.org/ft_gateway.cfm?id=507655type=pdf? Thanks in advance, Joel -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Thread blocked indefinitely
I got a copy, thanks! On Dec 2, 2005, at 6:47 PM, Greg Woodhouse wrote: Did anyone ever send you a copy of this paper? I'm an ACM member, so I could forward it to you if need be. -- http://wagerlabs.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] syntactic sugar for comonads
Hi, I'm wondering about a syntactic sugar for comonads. These are still very new to me, but it seems like their usage will become much more common once manipulations are more convenient (I believe this was the case with monads and arrows, correct?). Here's an example for motivation. Consider the data type data Stream a = a : Stream a and suppose we want to write a function movingWindow :: Stream a - Stream [a] so that, for example, movingWindow 3 (1 : 2 : 3 : ...) evaluates to [1,2,3] : [2,3,4] : [3,4,5] : ... Recognizing Stream as a comonad, this is pretty easy: movingWindow n s = s = (take n . toList) toList :: Stream a - [a] toList (x : xs) = x : toList xs If the second argument of (=) is written in lambda form, this comes out as movingWindow n s = s = \x - take n $ toList x This looks analogous to the way do is translated for monads, so a sugary alternative could be movingWindow n s = do x - s take n $ toList x Note that the presence of - tells us we're in a comonad, rather than a monad. I'm not at all stuck on this, but I think it would be good to get the ball rolling. What do you think? Chad Scherrer Computational Mathematics Group Pacific Northwest National Laboratory Time flies like an arrow; fruit flies like a banana. -- Groucho Marx ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: :t main
See: http://haskell.org/pipermail/haskell-cafe/2003-January/003794.html The OI comonad as previously envisioned breaks referential transparency. I/O just doesn't seem to be something which one can easily do comonadically, since once coeval/extract is applied, you're back to plain values, and there's no imposition of sequencing. - Cale On 02/12/05, Scherrer, Chad [EMAIL PROTECTED] wrote: From: Bulat Ziganshin [EMAIL PROTECTED] Hello Chad, Wednesday, November 30, 2005, 5:07:02 AM, you wrote: SC I've been reading some of the articles about comonads, and I thought SC the idea of giving main the type OI () - () was pretty interesting. it looks interesting. what are you reading? -- Best regards, Bulatmailto:[EMAIL PROTECTED] I'm reading the articles by Kieburtz and Uustalu linked from this page http://haskell.org/hawiki/CoMonadArticles On checking this again, I can't find the reference to the types I mentioned -- It may have just been the result of my reading the articles and letting the ideas simmer in my head, combined with a lack of rereading them before posting. I still need to read things through more carefully to be sure I understand it all correctly. In any case, here's the idea (still evolving, of course). There are safe functions of the form a - IO b but not IO a - b Dually, you should be able to write functions OI a - b but not a - OI b Now, suppose you want to read stdin, apply f to it, and print the result. The current standard is something like main = do s - getContents print $ f s or main = getContents = (print . f) But it's simpler to write main = print . f . coGetContents where coGetContents :: OI () - String f :: String - a print :: a - IO () Of course, changing the type of main alltogether is probably a bad idea, because it would break too much code. But maybe allowing constructions like this would be reasonable? Alternatively, there could be a nice way to write toMain :: (OI () - IO ()) - IO () My first thought is toMain f = f $ OI () but somehow this seems to easy, and I'm worried about the type safety. - Chad Scherrer Computational Mathematics Group Pacific Northwest National Laboratory Time flies like an arrow; fruit flies like a banana. -- Groucho Marx ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: :t main
From: Cale Gibbard [mailto:[EMAIL PROTECTED] See: http://haskell.org/pipermail/haskell-cafe/2003-January/003794.html The OI comonad as previously envisioned breaks referential transparency. I/O just doesn't seem to be something which one can easily do comonadically, since once coeval/extract is applied, you're back to plain values, and there's no imposition of sequencing. - Cale Hmm, I hadn't seen that. The asymmetry is pretty frustrating in that case. After poking around a bit more, I (re)discovered some discussion of this on Hawiki: http://www.haskell.org/hawiki/CoMonad After reading Dave Menendez's comments, I'm wondering... If we consider IO a = Realworld - (Realworld, a) then wouldn't we dually have something like OI a = (Realworld, Realworld - a)? Could this be what screws things up? Right now it seems like OI is acting like it has the same type as IO, with a different name. Chad Scherrer Computational Mathematics Group Pacific Northwest National Laboratory Time flies like an arrow; fruit flies like a banana. -- Groucho Marx ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe