2

I am trying to learn c# Language-ext from Paul Louth. I found the type OptionAsync is quite handy as it combines Tasks and Alternatives into one monad, making it a lot easier to work with both.

But I am confused how the await work with OptionAsync. I thought await OptionAsync<T> would return an Option, as Task and Option are two orthogonal concepts. I feel I am really awaiting the Option. However, the await OptionAsync would return a T not the Option.

My question is, should I never be in the situatoin where await OptionAsync is needed? How do I deal with the option if it's a None? Should I always use OptionAsync as a monad and never get out, where the optionality is probably handled along with the Task in the monad? There must be reason for the design.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
DavidY
  • 357
  • 5
  • 15

1 Answers1

3

When you 'stack' two monads (like Task and Option) you get a combination that abstracts the 'effects' from the underlying value(s) contained in it.

For instance, OptionAsync<int> indicates that you may or may not have an int , asynchronously delivered. 'May or may not' because of the Option, and 'asynchronously delivered' because of the Async. These are the effects.

When you write monadic expression (e.g. with await) you operate on the value 'inside' of the monad - i.e. the T. In other words, you've now abstracted away the effects so that you can focus on working on the value. I don't really know LanguageExt, but I'm assuming that it makes OptionAsync<T> awaitable, which you can always do with a monad.

The way Option works in general is that if the value isn't there, the entire expression short-circuits so that subsequent expressions don't run. The return value will also be an AsyncOption value, and if any one of the values along the way was None, the final result will also be None.

If you really want to deal explicitly with the Option value, just work with Task<Option<T>>. The whole point of combining the two into OptionAsync<T> is that you don't have to do that - until, perhaps, the very end.

You can convert an OptionAsync<T> to a Task<Option<T>> with the ToOption() method.

Option is also known as Maybe. With that in mind, perhaps my article Asynchronous Injection is useful. In it, at least, I attempt to explain the underlying concepts.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Thank you so much @Mark Seemann for the explanation. I think now I got it. If I have a need to get Option then I should use Task – DavidY Feb 27 '22 at 00:00