我是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]
,对吗?
如果是这样,则[User]
从中提取列表后users :: Maybe [User]
,您面临的问题是针对每个 进行单调操作(以获取网页)User
。在此有一个方便的组合器Control.Monad
:
mapM :: (Monad m) => (a -> m b) -> ([a] -> m [b])
可以根据您的情况专门进行以下操作:
mapM :: (User -> IO EnrichedUser) -> ([User] -> IO [EnrichedUser])
这就是说,如果您知道如何编写一个接受a的函数User
并创建一个将创建an的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 do-block中):
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
其他一切都将保持不变。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句