
On Thu, 21 Sep 2006 01:52:38 -0300, Donald Bruce Stewart
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