我应该如何从Haskell中的多个网络请求创建数据结构



我是Haskell的新手

我想构建一个数据结构,该数据结构是由我的应用程序中的两个HTTP请求构建的。

我的第一个请求获取了一个基本的用户列表,我可以选择将decode转到Maybe [User]

 r <- getWith opts "https://www.example.com/users"
 let users = decode $ r ^. responseBody :: Maybe [User]

但是,如果我想通过为

之类的操作来调用第二个用户来丰富用户数据
r2 <- getWth opts "https://www.example.com/users/{userid}/addresses"
let enrichedUser = decode $ r2 ^. responseBody :: Maybe EnrichedUser

我无法在一分钟内将这些部分拼凑在一起。我在do块中,这是期望IO ()

任何帮助将不胜感激!

我假设enrichedUser的类型应该是Maybe EnrichedUser而不是Maybe [EnrichedUser],对吗?

如果是这样,在从users :: Maybe [User]中提取[User]列表后,您面临的问题正在为每个 User运行一个monadic操作(以获取网页)。Control.Monad中有一个方便的组合:

mapM :: (Monad m) => (a -> m b) -> ([a] -> m [b])

可以在您的情况下专门为:

mapM :: (User -> IO EnrichedUser) -> ([User] -> IO [EnrichedUser])

这说明,如果您知道如何编写一个符合User并创建IO操作的函数,以创建EnrichedUser,则可以使用mapM将其转换为一个列表[User]并创建IO操作的函数创建整个列表[EnrichedUser]

在您的应用程序中,我想以前的功能看起来像:

enrich :: User -> IO EnrichedUser
enrich u = do
    let opts = ...
    let url = "https://www.example.com/users/" 
              ++ userToUserID u ++ "/addresses"
    r2 <- getWith opts url
    let Just enrichedUser = decode $ r2 ^. responseBody
    return enrichedUser
  where decode = ...

然后您可以写(在IO doblock中):

r <- getWith opts "https://www.example.com/users"
let Just users = decode $ r ^. responseBody
enrichedUsers <- mapM enrich users
-- here, enrichedUsers :: [EnrichedUser]
...etc...

我在此处省略了Maybe处理。如果富集失败,您可能希望以某种方式将常规User胁到默认的EnrichedUser,因此您要修改enrich功能的底部以读取:

let enrichedUser = case decode $ r2 ^. responseBody of
    Nothing -> defaultEnrichment u
    Just e  -> e
return enrichedUser

,其他一切都将保持不变。

相关内容

  • 没有找到相关文章

最新更新