Testing IO based monads and functions

Hey Haskellers, I had a design question: I'm using Haskell for the first time for something other than a simple toy application. I notice I'm coming up with a lot of IO based APIs that looks something like this: type UserInfo = (String, String) -- (name, password) getMagicNumberFromHTTPServer :: UserInfo -> IO (Maybe Int) getMagicNumberFromHTTPServer user = do let curlHTTPRequest = ... --Setup curl HTTP request httpRepsponse <- ... -- Make curl HTTP request return $ tryGetMagicNumberFromResponse httpResponse I like this API, because it's easy to understand. However, I find it hard to test. In OO land, I'd create a mock CurlHTTPRequest object and pass that into the magic number logic and test for the correct usage of the curl library. Is there a FP way of achieving the same goals? I suppose given the example above I could break down the above into several smaller pure functions and test them. I don't know if this strategy will hold-up when dealing with more complex monads. Thanks for your time, Dave

On Thu, Jan 26, 2012 at 11:01 PM, David Hinkes
type UserInfo = (String, String) -- (name, password)
getMagicNumberFromHTTPServer :: UserInfo -> IO (Maybe Int) getMagicNumberFromHTTPServer user = do let curlHTTPRequest = ... --Setup curl HTTP request httpRepsponse <- ... -- Make curl HTTP request return $ tryGetMagicNumberFromResponse httpResponse
One possible way would be having class (Functor m, Monad m) => CurlMonad m where curlRequest :: ... -> m ... instance CurlMonad IO where ... getMagicNumberFromHttpServer :: CurlMonad m => UserInfo -> m (Maybe Info) getMagicNumberFromHttpServer user = do httpResponse <- curlRequest ... return $ tryGetMagicNumberFromResponse httpResponse Now on your tests you could have data Mock a = ... instance CurlMonad Mock where ... where your Mock instance doesn't really use Curl. HTH, =) -- Felipe.
participants (2)
-
David Hinkes
-
Felipe Almeida Lessa