我是一名新手haskell程序员,我正在尝试编写一些Haskell cgi,它将从MySQL DB中读取并输出JSON.我能够生成正确的JSON,但无法正确获取数据类型以便能够正确输出JSON.我也认为我主要是在考虑势在必行.这是我的代码.请注意,getTopBrands提供了json输出.
我的问题是我无法弄清楚如何从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
Run Code Online (Sandbox Code Playgroud)
正如Niklas B所说,getTopBrands进入IO是对的,因为它取决于I/O. 我猜您的问题是,当您尝试直接使用它时,您会收到类型错误,
cgiMain :: CGI CGIResult
cgiMain =
do out <- getTopBrands 10 1
setHeader "Content-type" "application/json"
output $ renderHtml page out
Run Code Online (Sandbox Code Playgroud)
因为do-block中的所有语句必须属于同一个monad,并且块的其余部分都在CGI.但是,CGI是一个MonadIO,因此你可以简单地liftIO进入CGI,
cgiMain :: CGI CGIResult
cgiMain =
do out <- liftIO $ getTopBrands 10 1
setHeader "Content-type" "application/json"
output $ renderHtml page out
Run Code Online (Sandbox Code Playgroud)
尼克拉斯提出的下一点也是对的,第二个Integer论点getTopBrands应该是真的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
Run Code Online (Sandbox Code Playgroud)
只是传递你分支的条件.
尼克拉斯的第三点
我也不明白为什么
convPublicBrandEntrytoJSON需要生活IO,但由于你没有提供它的定义,我不能在这里建议改进.
也看起来非常有效,转换通常是纯函数.如果它出现的唯一原因IO是能够写作
json <- convPublicBrandEntrytoJSON brandlist
Run Code Online (Sandbox Code Playgroud)
你应该知道你可以在do-block中绑定纯函数的结果
let json = convPublicBrandEntrytoJSON brandlist
Run Code Online (Sandbox Code Playgroud)
使用let.