4

私は初心者の haskell プログラマーで、MySQL DB から読み取り、JSON を出力する Haskell cgi を作成しようとしています。正しい JSON を生成することはできますが、データ型を正しく取得して JSON を正しく出力することができません。私はまた、私は主にまだ不可欠なことを考えていると思います。これが私のコードです。getTopBrands は json 出力を提供することに注意してください。

私の問題は、「IO [Char]」ではなく「[Char]」を getTopBrands から返す方法がわからないことです。私にはまだ不可欠なことを考えているように見えます。これを修正するための指針、提案をいただければ幸いです。残りのコードを提供する必要がある場合はお知らせください。

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
4

1 に答える 1

8

Niklas B が言ったように、I/O に依存するので、入っているgetTopBrandsのは正しいことです。IOあなたの問題は、それを直接使用しようとすると、型エラーが発生することだと思います。

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

do ブロック内のすべてのステートメントは同じモナドに属している必要があり、残りのブロックはCGI. しかし、CGIは であるため、単純に に変換MonadIOできます。liftIOCGI

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

Niklas が提起した次の点も正しいです。 の 2 番目Integerの引数はgetTopBrands実際にはBool. ただし、現在のタイプであっても、コードの重複はまったく不要であり、2 つの分岐の違いは単に への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

分岐した条件を渡すだけです

ニクラスの 3 番目のポイント

convPublicBrandEntrytoJSONに住む必要がある理由もわかりませんIOが、その定義を提供していないため、ここで改善を提案することはできません.

も非常に有効に見えます。通常、変換は純粋な関数になります。それが入っている唯一の理由がIO書く能力である場合

json <- convPublicBrandEntrytoJSON brandlist

純粋な関数の結果を do ブロックにバインドできることに注意してください。

let json = convPublicBrandEntrytoJSON brandlist

を使用してlet

于 2013-04-10T18:29:29.487 に答える