Why does Command::perform need a callback?

current function:

pub fn perform<A>(
    future: impl Future<Output = A> + 'static + MaybeSend,
    f: impl FnOnce(A) -> T + 'static + MaybeSend,
) -> Command<T> {
    use futures::FutureExt;
    Command::single(Action::Future(Box::pin(future.map(f))))
}

Can be used like Command::perform(future, callback)
But often we have futures that directly return a message, making the callback boilerplate:
Command::perform(future, |x| x)

What if we just deleted the second argument entirely?

Simplifies the identity case:
Command::perform(future)
Doesn’t really complicate the other case:
Command::perform(future.map(callback))

if anything, I’d argue it’s more clear what’s going on here, rather than having to understand how perform actually uses the callback.

You shouldn’t tie your futures to a Message, since messages are UI-specific.