我假设的类型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])
这就是说,如果您知道如何编写一个接受 aUser并创建一个将创建一个 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
其他一切都将保持不变。