I noticed that Async has a Functor instance, which changes the result of an Async. But it (necessarily) does so entirely lazily; there's no way to ensure that computation is completed by the time wait returns. I suggest adding the following (by whatever name you like):
mapAsync :: (a -> Solo b) -> Async a -> Async b
mapAsync f (Async a w) = Async a $ w >>= \case
Left e -> pure (Left e)
Right r | MkSolo r' <- f r -> pure (Right r')