On Oct 15, 2007, at 19:00 , ChrisK wrote:

Brandon S. Allbery KF8NH wrote:
Use the source of unsafePerformIO as an example of how to write code
which passes around RealWorld explicitly, but without unencapsulating it
like unsafePerformIO does.

The main problem here, I think, is that because all the GHC runtime's
functions that interact with RealWorld (aside from unsafe*IO) are
themselves only exported wrapped up in IO, you can't (as far as I know) get at the lower level internal (e.g.) putStrLn' :: RealWorld -> String -> (# RealWorld,() #) to do I/O in a direct/explicit/non-monadic style.
In theory, one could export those and use them directly.

Well, if you import GHC.IOBase then you get

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

unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))
unIO (IO a) = a

Then the type of putStrLn:

-- putStrLn :: String -> IO ()

means that putStrLn' can be defined as

putStrLn' :: String -> State# RealWorld -> (# State# RealWorld, a #)
putStrLn' = unIO . putStrLn

Now you have the unboxed tuple and need to work with many 'case' statements to
accomplish anything.

Also you need to get you hand on State# RealWorld either
(1) Honestly, by wrapping your code in IO again and using it normally
  (2) From a copy, via unsafeInterleaveIO
  (3) From nowhere, via unsafePerformIO

(4) Honestly but unwrapped, by defining "main" in the same desugared way (takes State# RealWorld and returns (# State# RealWorld,a #) (or (# State# RealWorld,() #) if you stick to the H98 definition of main's type), allowing the runtime to pass it in and otherwise not doing anything other than propagating it.

My real problem was that I incorrectly recalled IO's type to be based on ST, not State (i.e. had a forall to prevent anything from being able to do anything to/with the State# RealWorld other than pass it on unchanged without triggering a type error). I should have realized that was wrong because unsafePerformIO is itself expressible in Haskell (-fglasgow-exts is needed to make # an identifier character and to enable unboxed types and unboxed tuples, but does not make it possible to cross an existential type barrier).

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