RE: [Haskell-cafe] Project postmortem

2005-12-02 Thread Simon Marlow
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

2005-12-02 Thread Tomasz Zielonka
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

2005-12-02 Thread Simon Marlow
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

2005-12-02 Thread Simon Marlow
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)

2005-12-02 Thread Joel Reymont

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

2005-12-02 Thread Sven Panne
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 ; -))

2005-12-02 Thread Joel Reymont

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 ; -))

2005-12-02 Thread Simon Marlow
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)

2005-12-02 Thread Simon Marlow
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 ; -))

2005-12-02 Thread Joel Reymont


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 ; -))

2005-12-02 Thread Simon Marlow
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

2005-12-02 Thread Scherrer, Chad
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 ; -))

2005-12-02 Thread Joel Reymont
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)

2005-12-02 Thread Joel Reymont

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

2005-12-02 Thread Joel Reymont

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

2005-12-02 Thread Joel Reymont

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

2005-12-02 Thread Scherrer, Chad
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

2005-12-02 Thread Cale Gibbard
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

2005-12-02 Thread Scherrer, Chad
 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