Magnus Therning asked:
> but how do I go about creating a finite list, e.g. a list that ends as
> soon as 'q' is pressed?
A slightly different approach that doesn't use anything unsafe:
What you want is to return something like an IO [Char] but it needs to
be able to interleave IO. A list of type [Char] is essentially a
solution to the equation
X = Maybe (Char,X)
It's either the empty list (represented by Nothing) or Just a pair of
the head and tail of the list. But this doesn't allow us to
intersperse IO along the computation of the list. In order to to that
we need a solution to
X = IO (Maybe (Char,X))
So define
data X = X { unX :: IO (Maybe (Char,X)) }
We can now write the 'q' terminated list as
test = X $ do
a <- getChar
if a=='q'
then return Nothing
else return (Just (a,test))
For all intents and purposes, this is what you want. It reads
characters until it reaches a 'q' and then returns IO Nothing.
To make use of this we can write something like this to print out the
contents of the list:
test2 :: X -> IO ()
test2 test = do
a <- unX test
case a of
Nothing -> return ()
Just (a,b) -> do
print a
test2 b
'test2 test' now prints out one of these q-terminated strings. There
is a bit of clutter because of the X and unX. And it's slightly
wordier because we're using Maybe instead of the nice Haskell List
notation. But I think it does exactly what you want. In particular we
have sepration of concerns - the object 'test' is in charge of
generating data and test2 is responsible for reading it, without
unsafe operations. And it seems to print the characters one at a time
as they are entered (with ghc).
--
Dan