【发布时间】:2015-08-22 00:41:39
【问题描述】:
我正在尝试构建一个 Haskell 客户端来使用 RESTful JSON API。我想获取一个页面,然后从响应中获取“next_page”键,并将其提供给另一个 api 请求的查询参数。我想继续这样做,直到我浏览完所有项目。在 Haskell 中最干净的方法是什么?我现在正在使用显式递归,但我觉得必须有更好的方法,也许是使用 writer 或 state monad。
编辑:添加了我的代码。我知道我在滥用 fromJust。
data Post = Post {
title :: !Text,
domain :: !Text,
score :: Int,
url :: !Text
} deriving (Show)
instance FromJSON Post where
parseJSON (Object v) = do
objectData <- v .: "data"
title <- objectData .: "title"
domain <- objectData .: "domain"
score <- objectData .: "score"
url <- objectData .: "url"
return $ Post title domain score url
data GetPostsResult = GetPostsResult {
posts :: [Post],
after :: Maybe Text
} deriving (Show)
instance FromJSON GetPostsResult where
parseJSON (Object v) = do
rootData <- v .: "data"
posts <- rootData .: "children"
afterCode <- rootData .:? "after"
return $ GetPostsResult posts afterCode
fetchPage:: Text -> IO (Maybe ([Post],Maybe Text))
fetchPage afterCode = do
let url = "https://www.reddit.com/r/videos/top/.json?sort=top&t=day&after=" ++ unpack afterCode
b <- get url
let jsonBody = b ^. responseBody
let postResponse = decode jsonBody :: Maybe GetPostsResult
let pagePosts = posts <$> postResponse
let nextAfterCode = after $ fromJust postResponse
if isNothing pagePosts then return Nothing else return (Just (fromJust pagePosts,nextAfterCode))
getPosts :: Text -> [Post] -> IO [Post]
getPosts x y = do
p <- liftIO $ fetchPage x
let posts = fst (fromJust p)
let afterParam = snd (fromJust p)
case afterParam of
Nothing -> return []
Just aff -> getPosts aff (posts ++ y)
main = do
a <- getPosts "" []
print a
【问题讨论】:
-
代码。向我们展示您的代码。
-
添加了代码。我应该更好地处理 fromJust 并且我可以将它分解为一些更小的函数,但现在我只是试图获得分页机制。
-
考虑使用默认的
fromJSON实例。只需让你的类型派生Generic(来自GHC.Generics)然后写instance FromJSON Post。