Haskell设计:与IO挣扎

时间:2013-04-10 17:05:55

标签: haskell

我是一名新手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

1 个答案:

答案 0 :(得分:8)

作为Niklas B saidgetTopBrands中的IO是正确的,因为它取决于I / O.我猜您的问题是,当您尝试直接使用它时会出现类型错误,

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

因为do-block中的所有语句必须属于同一个monad,而块的其余部分都在CGI中。但是,CGIMonadIO,因此您只需将其liftIO转换为CGI

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

Niklas提出的下一点也是对的,Integer的第二个getTopBrands论点应该是Bool。但是,即使使用当前类型,代码重复也完全没有必要,两个分支之间的差异只是Bool的{​​{1}}参数,所以

getBrands

只是将你分支的条件传递给

尼古拉斯&#39;第三点

  

我也不明白为什么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

你应该知道你可以在do-block中绑定纯函数的结果

json <- convPublicBrandEntrytoJSON brandlist

使用let json = convPublicBrandEntrytoJSON brandlist