As Niklas B said , getTopBrands is in IO correctly, as it depends on I / O. I think your problem is that you get a type error when you try to use it directly,
cgiMain :: CGI CGIResult cgiMain = do out <- getTopBrands 10 1 setHeader "Content-type" "application/json" output $ renderHtml page out
since all instructions in the do block must belong to the same monad, and the rest of the block is in CGI . But CGI is MonadIO , so you can just liftIO insert it into CGI ,
cgiMain :: CGI CGIResult cgiMain = do out <- liftIO $ getTopBrands 10 1 setHeader "Content-type" "application/json" output $ renderHtml page out
The next point that Niklas raised is also right, the second argument of Integer getTopBrands should really be Bool . However, even with its current type, code duplication is completely unnecessary, the difference between the two branches is just a Bool argument for getBrands , therefore
getTopBrands :: Integer -> Integer -> IO [Char] getTopBrands limit sorted = do let temp = 0 dbh <- connect "127.0.0.1" "ReachOutPublicData" "root" "admin" "/tmp/mysql.sock" brandlist <- getBrands dbh limit (sorted == 1) json <- convPublicBrandEntrytoJSON brandlist return $ LBS.unpack json
just pass it the condition in which you are branched.
Third point of Niklas
I also do not understand why convPublicBrandEntrytoJSON will need to live in IO , but since you did not specify its definition, I cannot offer an improvement here.
also looks very correct, conversion is usually a pure function. If the only reason she is in IO is the ability to write
json <- convPublicBrandEntrytoJSON brandlist
you should know that you can bind the results of pure functions in a do-block
let json = convPublicBrandEntrytoJSON brandlist
using let .