protocol HasDatabase { func database: Database }
protocol HasHttpClient { func httpClient: HttpClient }

func fetchAndSave<M: MonadReader>(userId: Int)-> M.M<()>
    where M.Env = HasDatabase & HasHttpClient {
  #monadic {
    api <- M.ask().map { $0.httpClient }
    db <- M.ask().map { $0.database }

    user <- api.fetch(userId: userId)
    db.save(user: user)
  }
}

Explanation:

// #monadic is a freestanding macro, with the addition of generic associated 
// types, this macro should be possible to make with no additional language 
// changes. It just converts it into a chain of flatMap calls,
// this being equivalent to the above:

func fetchAndSave<M: MonadReader>(userId: Int)-> M.M<()>
    where M.Env = HasDatabase & HasHttpClient {
  M.ask().map { $0.httpClient }.flatMap { api in
    M.ask().map { $0.database }.flatMap { db in
      api.fetch(userId: userId).flatMap { user in
        db.save(user: user)
      }
    }
  }
}