3

WAI を使用して API を起動および実行するための基本に苦労しています。IO主な問題は、すべての感染に対処することです。モナドをよりよく理解すれば、私の問題は解決すると思いますが、この質問に対する答えが良い出発点になることを願っています。

/api/my-data以下は、ルート URL で静的な html ページを提供し、対応するユーザーのデータを返すユーザー名を持つリクエストを受け入れる短い例です。マップ ルックアップを実行し、データを取得し、結果を json にエンコードして送り返すIO Bytestringリクエストの使用方法がわかりません。body

を使用fmapして抽出しBytestring、それunpackを検索用の文字列に変換しようとしましたが、何をしても、いまいましいIOモナドに関連する型エラーを追跡することになります。

とにかく、ここに関連するコードがあります:

{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import qualified Data.Map as Map
import Data.Aeson
import Network.Wai
import Network.Wai.Parse
import Network.Wai.Middleware.Static
import Network.HTTP.Types
import Network.Wai.Handler.Warp (run)

userInfo :: Map.Map String (Map.Map String String)
userInfo = Map.fromList [("jsmith", Map.fromList [("firstName", "John"),
                                                  ("lastName", "Smith"),
                                                  ("email", "jsmith@gmail.com"),
                                                  ("password", "Testing012")]),
                         ("jeff.walker", Map.fromList [("firstName", "Jeff"),
                                                       ("lastName", "Walker"),
                                                       ("email", "jeff.walker@gmail.com"),
                                                       ("password", "Testing012")])]

getUserInfo :: B.ByteString -> Map.Map String String
getUserInfo body =
  case Map.lookup (B8.unpack body) userInfo of
    (Just x) -> x
    Nothing  -> Map.empty

app :: Application
app request respond = do
  case rawPathInfo request of
    "/"            -> respond index
    "/api/my-data" -> respond $ myData (getUserInfo (requestBody request))
    _              -> respond notFound

index :: Response
index = responseFile
  status200
  [("Content-Type", "text/html")]
  "../client/index.html"
  Nothing

myData :: IO (Map.Map String String) -> Response
myData user = responseLBS
  status200
  [("Content-Type", "application/json")]
  (encode user)


notFound :: Response
notFound = responseLBS
  status404
  [("Content-Type", "text/plain")]
  "404 - Not Found"

main :: IO ()
main = do
  putStrLn $ "http://localhost:8080/"
  run 8080 $ staticPolicy (addBase "../client/") $ app

これにより、次のエラーが発生します。

src/Core/Main.hs:32:54:
    Couldn't match expected type ‘B8.ByteString’
                with actual type ‘IO B8.ByteString’
    In the first argument of ‘getUserInfo’, namely
      ‘(requestBody request)’
    In the first argument of ‘myData’, namely
      ‘(getUserInfo (requestBody request))’

andの型をgetUserInfoandmyDataに簡単に変更できますが、型エラーが増えてしまいます。タイプは私の頭をぐるぐるさせています。IO Bytestring -> IO (Map.Map String String)IO (Map.Map String String) -> Response

4

1 に答える 1

2

requestBody次のタイプがあるので:

requestBody :: Request -> IO ByteString

getUserInfo結果の式は、 を受け入れるに直接渡すことはできませんByteString

あなたができることは、それApplicationが単純Request -> (Response -> IO ResponseReceived) -> IO ResponseReceivedであり、appあなたがモナドにいるとすれば、次のような表記でをIO抽出するByteStringことです:do

str <- requestBody request 

そして、次のようstrにに渡しgetUserInfoます。

app :: Application
app request respond = do
  str <- requestBody request
  case rawPathInfo request of
    "/"            -> respond index
    "/api/my-data" -> respond $ myData (getUserInfo str)
    _              -> respond notFound

この時点で、myData単に受け入れることができますMap

myData :: Map.Map String String -> Response

ただし、WAI を深く掘り下げる前に、モナドと IO 全般についてもっと読むべきです。

于 2015-04-19T10:45:46.917 に答える