[Haskell-cafe] Re: do

ChrisK haskell at list.mightyreason.com
Mon Oct 15 19:00:22 EDT 2007

Brandon S. Allbery KF8NH wrote:
> On Oct 15, 2007, at 13:32 , Peter Verswyvelen wrote:
>> jerzy.karczmarczuk at info.unicaen.fr wrote:
>>>> Yes, *different approach*. So, there *are* differences. Compilers,
>>>> anyway,
>>>> are special applications. I wanted to see - responding to Brandon - a
>>>> "normal" Haskell program, which does IO without monads, that't all.
>>>> The problem is then when you hide something, you hide. It is
>>>> possible to
>>>> superpose a kind of monadic framework on unique worlds, files, etc. in
>>>> Clean, but the reverse operation goes beyond my horizons.
>>>> Some examples, anybody?
>> Ah yes, I see what you mean now. I have no idea, I guess only
>> unsafePerformIO will allow you to do something like that... But that
>> will completely break referential transparency. But I really don't
>> know. What do the experts have to say?
> 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

> (Actually, as a practical matter, IIRC GHC "knows about" RealWorld and
> removes all of it when generating cmm code once it's done the job of
> sequencing Haskell evaluation; I'm not sure how well that would work if
> you wrote I/O in direct/explicit style.  unsafePerformIO doesn't really
> count for that because it removes the RealWorld itself.)

More information about the Haskell-Cafe mailing list