我正在为使用 WAI 启动和运行 API 的基础知识而苦苦挣扎。主要问题是处理IO
感染一切。我相信一旦我更好地理解 Monads,我的问题就会解决,但希望这个问题的答案将是一个很好的起点。
以下是一个简短示例,它在根 url 上提供静态 html 页面,并接受带有用户名的请求,该用户名/api/my-data
应返回相应用户的数据。我不知道如何使用IO Bytestring
请求body
来进行地图查找、检索数据并将结果发送回以 json 编码的结果。
我尝试使用fmap
提取Bytestring
然后unpack
将其转换为字符串以进行查找,但无论我做什么,我最终都会追逐与该死的IO
monad 相关的类型错误。
无论如何,这是相关的代码:
{-# 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))’
我可以轻松地更改和的类型,getUserInfo
但myData
最终IO Bytestring -> IO (Map.Map String String)
会IO (Map.Map String String) -> Response
出现更多类型错误。类型让我头晕目眩。