2013-04-10 62 views
4

我是一個新手haskell程序員,我正在嘗試編寫一些Haskell cgi,它將從MySQL DB讀取並輸出JSON。我能夠生成正確的JSON,但無法正確獲取數據類型以正確輸出JSON。我也認爲我主要還是認爲勢在必行。這是我的代碼。請注意,getTopBrands提供了json輸出。Haskell設計:苦於IO

我的問題是,我無法弄清楚如何從getTopBrands返回「[Char]」而不是「IO [Char]」。在我看來,我仍然認爲是必要的。任何指針,解決這個問題的建議將不勝感激。請讓我知道是否需要提供其餘的代碼。

RODB.hs:

{-# LANGUAGE RecordWildCards, OverloadedStrings, PackageImports #-} 

module Main where 

import RODB 
import ROOutput 
import System.Environment 
import Database.HDBC 
import Network.Socket(withSocketsDo) 
import Network.CGI 
import Text.XHtml 
import qualified "bytestring" Data.ByteString.Lazy.Char8 as LBS 
import Data.Aeson 

page :: Html 
page = body << h1 << str 

main = runCGI $ handleErrors cgiMain 

cgiMain :: CGI CGIResult 
cgiMain = 
    do out <- getTopBrands 10 1 
     setHeader "Content-type" "application/json" 
     output $ renderHtml page out 

getTopBrands :: Integer -> Integer -> IO [Char] 
getTopBrands limit sorted = 
    do let temp = 0 
     dbh <- connect "127.0.0.1" "ReachOutPublicData" "root" "admin" "/tmp/mysql.sock" 
     if sorted == 1 
     then do brandlist <- getBrands dbh limit True 
       json <- convPublicBrandEntrytoJSON brandlist 
       return $ LBS.unpack json 
     else do brandlist <- getBrands dbh limit False 
       json <- convPublicBrandEntrytoJSON brandlist 
       return $ LBS.unpack json 
+6

這裏的'IO'有什麼問題?畢竟,函數*的結果取決於I/O操作的結果,所以我不會考慮這種不好的風格。這裏更明顯的問題是'sorted'參數,它具有'Integer'類型。如果它的類型爲'Bool',則可以直接將它傳遞給'getBrands',而不會出現醜陋的分支和代碼重複。我也不明白爲什麼'convPublicBrandEntrytoJSON'需要住在'IO'中,但是由於你沒有提供它的定義,我不能在這裏提出改進。 – 2013-04-10 17:10:16

回答

8

由於Niklas B saidgetTopBrandsIO是是正確的,因爲它取決於I/O。我猜你的問題是,當你嘗試直接使用它,你得到一個類型錯誤,

cgiMain :: CGI CGIResult 
cgiMain = 
    do out <- getTopBrands 10 1 
     setHeader "Content-type" "application/json" 
     output $ renderHtml page out 

,因爲在一個do塊的所有語句都必須屬於同一個單子,和塊的其餘部分是在CGI。但是,CGIMonadIO,因此你可以簡單地liftIOCGI

cgiMain :: CGI CGIResult 
cgiMain = 
    do out <- liftIO $ getTopBrands 10 1 
     setHeader "Content-type" "application/json" 
     output $ renderHtml page out 

下一個點尼克拉斯上調也是正確的getTopBrands第二Integer參數應該真的是Bool。然而,即使使用其當前的類型,代碼重複是完全沒有必要的,這兩個分支之間的差異僅僅是Bool參數getBrands,所以

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 

只是通過它在其上支的條件。

尼克拉斯第三點

我也不明白爲什麼convPublicBrandEntrytoJSON需要住在IO,但因爲你沒有提供它的定義,我不能在這裏建議的改善。

也看起來非常有效,轉換通常是純函數。如果它爲什麼在IO的唯一理由是寫

json <- convPublicBrandEntrytoJSON brandlist 

的能力,你應該知道,你可以綁定的純函數結果使用let一個做塊

let json = convPublicBrandEntrytoJSON brandlist 

+0

謝謝Daniel,liftIO爲我做了這份工作。 – Animesh 2013-05-01 11:56:07