[Haskell-cafe] Re: [newbie] How to test this function?

Bruno Martínez br1 at internet.com.uy
Thu Sep 21 10:13:20 EDT 2006


On Thu, 21 Sep 2006 01:52:38 -0300, Donald Bruce Stewart  
<dons at cse.unsw.edu.au> 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



More information about the Haskell-Cafe mailing list