Haskell设计:与IO抗争
我是一个haskell程序员新手,我正在尝试编写一些haskell cgi,它将读取MySQL数据库并输出JSON。我能够生成正确的JSON,但无法正确获取数据类型以正确输出JSON。我还认为,我的主要想法仍然是必须的。这是我的密码。注意,getTopBrands提供json输出 我的问题是,我不知道如何从getTopBrands返回“[Char]”,而不是“IO[Char]”。在我看来,我仍然认为这是当务之急。如有任何关于解决此问题的建议,我们将不胜感激。请让我知道,如果我需要提供其余的代码 RODB.hs:Haskell设计:与IO抗争,haskell,Haskell,我是一个haskell程序员新手,我正在尝试编写一些haskell cgi,它将读取MySQL数据库并输出JSON。我能够生成正确的JSON,但无法正确获取数据类型以正确输出JSON。我还认为,我的主要想法仍然是必须的。这是我的密码。注意,getTopBrands提供json输出 我的问题是,我不知道如何从getTopBrands返回“[Char]”,而不是“IO[Char]”。在我看来,我仍然认为这是当务之急。如有任何关于解决此问题的建议,我们将不胜感激。请让我知道,如果我需要提供其余的代码
{-# 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
{-#语言记录通配符、重载字符串、PackageImports}
模块主要在哪里
进口RODB
输入输出
导入系统。环境
导入数据库.HDBC
导入网络套接字(带socketsdo)
导入网络.CGI
导入Text.XHtml
将符合条件的“bytestring”Data.bytestring.Lazy.Char8导入为LBS
导入数据.Aeson
页面::Html
page=bodyAs,getTopBrands
处于IO
中是正确的,因为它取决于I/O。我想你的问题是,当你试图直接使用它时,你会从中得到一个类型错误
cgiMain :: CGI CGIResult
cgiMain =
do out <- getTopBrands 10 1
setHeader "Content-type" "application/json"
output $ renderHtml page out
Niklas提出的下一点也是对的,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
您应该知道,您可以在do块中绑定纯函数的结果
let json = convPublicBrandEntrytoJSON brandlist
使用let
这里的IO
有什么问题?毕竟,函数的结果依赖于I/O操作的结果,所以我不会考虑这种坏的风格。这里更明显的问题是sorted
参数,其类型为Integer
。如果它有类型Bool
,您可以直接将它传递到getBrands
,而不需要丑陋的分支和代码复制。我也不明白为什么convPublicBrandEntrytoJSON
需要生活在IO
中,但由于您没有提供它的定义,我无法在此提出改进建议。谢谢Daniel,liftIO帮我完成了这项工作。
json <- convPublicBrandEntrytoJSON brandlist
let json = convPublicBrandEntrytoJSON brandlist