7

ページ分割された API エンドポイントから 2 ページのデータを取得する次のコードがあります。queryデータが見つからなくなるまでページを取得し続けるように関数を変更したいと思います (そのためtake 2、以下のコードを API 応答を確認するものに置き換えます)。

query私の質問は、関数を関数に変更せずにこれを達成できるかどうかですIO。もしそうなら、どうすればそれについて行くことができますか。そうでない場合、再帰関数を書かずにこれを行う方法はありますか?

コードは次のとおりです。

#!/usr/bin/env stack

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import Servant.Client
import Network.HTTP.Client (newManager, defaultManagerSettings)

import Data.Proxy
import Servant.API

import Data.Aeson
import GHC.Generics


-- data type
data BlogPost = BlogPost
  { id :: Integer
  , title :: String
  } deriving (Show, Generic)

instance FromJSON BlogPost


-- api client
type API = "posts" :> QueryParam "_page" Integer :> Get '[JSON] [BlogPost]
api :: Proxy API
api = Proxy
posts :: Maybe Integer -> ClientM [BlogPost]
posts = client api


-- query by page
query :: ClientM [[BlogPost]]
query = sequence $ take 2 $ map posts pages
  where
    pages = [Just p | p <- [1..]]

-- main
main :: IO ()
main = do
  manager' <- newManager defaultManagerSettings
  let url = ClientEnv manager' (BaseUrl Http "jsonplaceholder.typicode.com" 80 "")
  posts' <- runClientM query url
  print posts'

私はこれtakeWhileMを行うために使用しようとしましたが、最終的にクエリをIO関数にして渡しurlました。それはかなり恐ろしく見え始めていて、タイプを一致させることができませんでした(どちらが何であるかでは(a -> m Bool) -> m [a] -> m [a]なく、もっと似たものが必要だと感じました.リストと出力リストは異なります (一方はモナドを持ち、もう一方はそうではありません))。(a -> m Bool) -> [a] -> m [a]takeWhileM

4

3 に答える 3