ページ分割された 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