On Thu, 21 Sep 2006 01:52:38 -0300, Donald Bruce Stewart <[EMAIL PROTECTED]> wrote:

First, how do I fix the identation of the if then else?
getList = find 5
    where find 0 = return []
          find n = do
            ch <- getChar
            if ch `elem` ['a'..'e']
                then do tl <- find (n-1)
                        return (ch : tl)
                else find n

OK. Thanks. I didn't find that one because it's not offered as an identation option in emacs haskell mode.

Second, I want to test this function, without hitting the filesystem. In C++ I would use a istringstream. I couldn't find a function that returns a Handle from a String. The closer thing that may work that I could find was making a pipe and convertind the file descriptor. Can I simplify that
function to take it out of the IO monad?  How?  I thought about
getContents, but that eats all input.

Refactor!
The reason your getList is hard to test, is that you're mixing side
effecting monadic code with pure computations. Let's untangle that, and
then test the the referentially transparent parts simply with
QuickCheck. And remember that since getContents uses lazy IO, it only
eats as much input as you ask it to.

So let's refactor this, partitioning off the side effecting IO code:

    getList :: IO [Char]
    getList = take5 `fmap` getContents -- a thin IO "skin"

    take5 :: [Char] -> [Char]
    take5 = take 5 . filter (`elem` ['a'..'e']) -- the actual worker

The problem is that getContents 'eats' stdin, which can't be used again. I'm forced to change all my IO code to the getContents way, which is not possible.

About QuickCheck: I'm going to check it out.  Thanks for the pointers.

Bruno

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

Reply via email to