On Oct 15, 2007, at 21:01 , Ryan Ingram wrote:

Oops, I read too fast, you mentioned that as #1.

On 10/15/07, ChrisK <[EMAIL PROTECTED]> wrote:
Also you need to get you hand on State# RealWorld either
(1) Honestly, by wrapping your code in IO again and using it normally

Silly me.

That makes two of us; my (4) is in fact his (1), I misunderstood the "wrapping your code in IO again".

For those trying to follow along with all this silliness, the secret to making this work is defining a runIO function --- which is *not* the same as unsafePerformIO, because that invokes the internal RealWorld# constructor to inject a "fresh" State# RealWorld, whereas we're using the one that we were legitimately passed:

runIO :: IO a -> State# RealWorld -> (# State# RealWorld,a #)
  runIO (IO f) s =  lazy (f s)

(See libraries/base/GHC/IOBase.lhs for why we need the GHC builtin "lazy" there.)

The reason for this is that IO is a "state-like" type:

  newtype IO a = IO (State# RealWorld -> (# State# RealWorld,a #))

Which is to say, it is a wrapper around a function which accepts a state and returns a "modified" (in our case, actually just passed through without even looking at it) state along with the result of a computation. The runIO function is just runState specialized to this newtype. (Because you can't pattern match on (IO (s -> (# s,a #))) in a function definition.)

I'm working on a "simple" example of how to do this without treating IO as a monad. So far it's proving a very concrete demonstration to me of why you do *not* want to do it this way, but instead should consider the monad your friend. :)

--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [EMAIL PROTECTED]
system administrator [openafs,heimdal,too many hats] [EMAIL PROTECTED]
electrical and computer engineering, carnegie mellon university    KF8NH


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to