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@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

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

Reply via email to