[Haskell-cafe] Re: do
Brandon S. Allbery KF8NH
allbery at ece.cmu.edu
Mon Oct 15 19:29:04 EDT 2007
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] allbery at kf8nh.com
system administrator [openafs,heimdal,too many hats] allbery at ece.cmu.edu
electrical and computer engineering, carnegie mellon university KF8NH
More information about the Haskell-Cafe
mailing list