[Haskell-cafe] Haskell soltion ofr I/O: is it monads or uniqueness types, after all?

Lennart Augustsson lennart at augustsson.net
Sat Feb 10 16:22:57 EST 2007


Hbc implements the IO type by request/response IO.  I.e., the original
Haskell I/O system.  People who assume IO involves some RealWorld being
passed around are just making unwarranted assumptions.  The Haskell
definition leaves the IO type abstract.

	-- Lennart

On Feb 10, 2007, at 19:16 , Stefan O'Rear wrote:

> Gah.  For the first time ever, I seem to have accidentally done a  
> reply to
> sender.  (IE Bulat please ignore this message)
>
> On Sat, Feb 10, 2007 at 07:25:19PM +0300, Bulat Ziganshin wrote:
>> Hello haskell-cafe,
>>
>> just another interesting discussion in russian forum raised such  
>> idea:
>>
>> we all say that monads are the haskell way to do i/o. is it true? may
>> be, uniqueness types, just like in Clean and Mercury, are real  
>> way, and
>> monads are only the way to write programs that use uniqueness types
>> easier?
>>
>> so, IO monad is like any other monad - it simplifies writing of
>> complex code, but by itself it don't solve any problems. all code  
>> that
>> can be written with monads can also be written using ordinal function
>> calls. we know it for IO monad too - in ghc, we can use low-level
>> representation of IO type and write imperative code without use of
>> any monad operators
>
> Just because Jhc, GHC, and Yhc (any others? any non-others?) all use
> RealWorld# tokens, doesn't mean it's the only way to implement IO.
> Note that unsafePerformIO will need to be a primitive...
>
> data Process = Getc (Char -Process)
>              | Putc Char (() -Process)
>              | forall a. NewIORef a (IORef a -Process)
>              | forall a. ReadIORef (IORef a) (a -Process)
>              | forall a. WriteIORef (IORef a) a (() -Process)
>              | Exit
> {- IORef is specifically mentioned because it is the canonical  
> example of something IO can do that 1.2-style streams can't -}
>
> type IO = Cont Process
> -- using Cont monad's monad
>
> getChar = Cont $ Getc
> putChar = Cont . Putc
> newIORef = Cont . NewIORef
> readIORef = Cont . ReadIORef
> writeIORef a b = Cont $ WriteIORef a b
> exit = Cont $ \_ -Exit
>
> {- in runtime, forgive my rusty C -}
>
> int main() {
>     init_runtime_foo();
>     thunk* tree = hseval("runCont main Exit")
>
>     while(1) {
>         whnf(tree);
> 	switch (tree->tag) {
> 	    case _Getc:
> 	        char ch = getchar();
> 		thunk* hch = hs_wrapchar(ch);
>                 tree = hsmkapp( tree->payload(0) , hch );
> 		continue;
> 	    ...
>             case _Exit:
>                 return 0;
>         }
>     }
> }
>
> of course, this doesn't refute the non-primitive-ness of IO, but it  
> does refute
> the uniqueness types part.
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe



More information about the Haskell-Cafe mailing list