RE: [Haskell] Why is newChan in the IO Monad?
Channels have identity, so allocating a new one is a side effecting operation. Having it outside the IO monad would require (for example): (newChan, newChan) = (let x = newChan in (x,x)) which is wrong. If you wrap newChan in unsafePerformIO then the compiler will feel free to apply rewrites like the above, which is unlikely to be what you wanted. Nick -----Original Message----- From: haskell-bounces@haskell.org [mailto:haskell-bounces@haskell.org] On Behalf Of S. Alexander Jacobson Sent: 23 April 2004 19:22 To: Haskell Mailing List Subject: [Haskell] Why is newChan in the IO Monad? Nothing actually happens when newChan is called except construction of a new datastructure. It would be nice to have non IO monad code be able to create a new Chan that gets passed to IO code that uses it somewhere else. Alternatively, is there a way to create a Chan outside the IO monad? -Alex- _________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Yes, that makes sense, but I'm ok with passing in an identity. I'd like a function like this: newChanSafe::Identity -> Chan a type Identity = Double -- or whatever -Alex- _________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com On Fri, 23 Apr 2004, Nick Benton wrote:
Channels have identity, so allocating a new one is a side effecting operation. Having it outside the IO monad would require (for example):
(newChan, newChan) = (let x = newChan in (x,x))
which is wrong. If you wrap newChan in unsafePerformIO then the compiler will feel free to apply rewrites like the above, which is unlikely to be what you wanted.
Nick -----Original Message----- From: haskell-bounces@haskell.org [mailto:haskell-bounces@haskell.org] On Behalf Of S. Alexander Jacobson Sent: 23 April 2004 19:22 To: Haskell Mailing List Subject: [Haskell] Why is newChan in the IO Monad?
Nothing actually happens when newChan is called except construction of a new datastructure. It would be nice to have non IO monad code be able to create a new Chan that gets passed to IO code that uses it somewhere else.
Alternatively, is there a way to create a Chan outside the IO monad?
-Alex-
_________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
On Friday 23 April 2004 20:05, S. Alexander Jacobson wrote:
Yes, that makes sense, but I'm ok with passing in an identity. I'd like a function like this:
newChanSafe::Identity -> Chan a type Identity = Double -- or whatever
As Nick observes, using this function would require you to pass around a supply of unique Identitys. If we assume you're going to have to do this, why not simplify things and pass around a list of newChans: type Identity = Chan Int withChan :: (Identity -> a) -> [Identity] -> (a,[Identity]) ... You can use unsafeInterleaveIO to create a lazy list of channels. Better yet, you can use unsafeInterleaveIO to create a lazy tree of channels so that splitting the supply is efficient. One minor detail left as an exercise: my definition of Identity is monomorphic but you probably want them to be polymorphic. This is a bit tricky to fix and will require a monad (or equivalent) to ensure that you don't allocate the same chan twice and then use it at different types. (Probably requires unsafeCast too.) -- Alastair Reid
If you want to pass in a splittable supply, I recommend saving yourself the trouble of building the plumbing. Instead, try the Supply library which I wrote a few years back: http://csg.lcs.mit.edu/~earwig/haskell-lib/index.html You can create a splittable supply of channels using
chanSupply <- ioSupply newChan
Nonetheless, the problem of generating polymorphic channels is still (as Alastair suggests) a bit of an exercise. You will need to create a polymorphic wrapper for the result of "newChan". -Jan-Willem Maessen jmaessen@alum.mit.edu Alastair Reid wrote:
On Friday 23 April 2004 20:05, S. Alexander Jacobson wrote:
Yes, that makes sense, but I'm ok with passing in an identity. I'd like a function like this:
newChanSafe::Identity -> Chan a type Identity = Double -- or whatever
As Nick observes, using this function would require you to pass around a supply of unique Identitys. If we assume you're going to have to do this, why not simplify things and pass around a list of newChans:
type Identity = Chan Int withChan :: (Identity -> a) -> [Identity] -> (a,[Identity]) ...
You can use unsafeInterleaveIO to create a lazy list of channels. Better yet, you can use unsafeInterleaveIO to create a lazy tree of channels so that splitting the supply is efficient.
One minor detail left as an exercise: my definition of Identity is monomorphic but you probably want them to be polymorphic. This is a bit tricky to fix and will require a monad (or equivalent) to ensure that you don't allocate the same chan twice and then use it at different types. (Probably requires unsafeCast too.)
-- Alastair Reid
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
participants (4)
-
Alastair Reid -
Jan-Willem Maessen - Sun Labs East -
Nick Benton -
S. Alexander Jacobson