Haskell设计:与IO抗争

Haskell设计:与IO抗争,haskell,Haskell,我是一个haskell程序员新手,我正在尝试编写一些haskell cgi,它将读取MySQL数据库并输出JSON。我能够生成正确的JSON,但无法正确获取数据类型以正确输出JSON。我还认为,我的主要想法仍然是必须的。这是我的密码。注意,getTopBrands提供json输出 我的问题是,我不知道如何从getTopBrands返回“[Char]”,而不是“IO[Char]”。在我看来,我仍然认为这是当务之急。如有任何关于解决此问题的建议,我们将不胜感激。请让我知道,如果我需要提供其余的代码

我是一个haskell程序员新手,我正在尝试编写一些haskell cgi,它将读取MySQL数据库并输出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
{-#语言记录通配符、重载字符串、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