Попытка выяснить, что вы спрашиваете. Я думаю, вы задаетесь вопросом, как учесть IO
действия, которые требуют времени, нет? Потому что если бы действие IO
было мгновенным, это не было бы вопросом. Хотя у меня все еще есть вопрос, что делает блок действия IO
, пока не наступит будущее, или он планирует его асинхронно?
Если это неблокирующий вызов, я бы сказал, что он должен дождаться завершения действия IO
. (Я бы также назвал это schedFuture
или что-то подобное, чтобы было ясно, что он не блокируется.) В противном случае у вас может быть случай, когда Future
находится в прошлом, но значение все еще недоступно, которые могут испортить логику функций, которые объединяют события и т. д.
Если это блокирующий вызов, я бы вместо этого предоставил
waitFuture :: Future a -> IO a
и позволить пользователю иметь дело с остальными (например, они могут fmap (const x)
в исходном будущем, если они хотят сохранить время, они могут использовать now :: IO (Future ())
, если они хотят, когда оно завершится, и т. Д.). Возможно, стоит предложить комбинаторы для них, если вы можете придумать для них хорошие имена, иначе они настолько просты, что я просто выбью.
Я также обнаружил, что при создании подобных систем полезно различать «1018» действия и действия, которые могут блокироваться. Я предполагаю, что это параллельно различию javascript между асинхронными и обычными вызовами стека. Есть много нечетких вопросов, подобных этому, и соответствующие очевидные ответы, как правило, зависят от этого различия.