[Haskell-cafe] Haskell soltion ofr I/O: is it monads or
uniqueness types, after all?
Stefan O'Rear
stefanor at cox.net
Sat Feb 10 14:16:19 EST 2007
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.
More information about the Haskell-Cafe
mailing list