spebbe / dartz

Functional programming in Dart
MIT License
749 stars 60 forks source link

Questions regarding dart async and Monads #101

Closed ace-99 closed 2 years ago

ace-99 commented 2 years ago

Hello - appreciate the library. I have experience in Haskell and with Kotlin + Arrow and this helps feel right at home learning this new language.

Two questions if you have the time.

  1. How do you best use async functions with monads?

    State(async runApp).run(initialState)

    This won't work and I know its because the type signature doesn't match for State but how can it be made to match? Lifting? Monad transformer with Future? I understand Future is a monad and there is the.traverseFuture() I may be missing something obvious.

  2. Chaining monads and futures. Is there a better way to write this?

    eitherOne()
    .bind((futureRight) => 
      futureRight.then((right) => 
        eitherTwo().bind((anotherRight) => 
          done(right, anotherRight))));

    Thinking along the lines of "do notation" or "for comprehension". And again is this the best way to deal with futures?

Much appreciated.

spebbe commented 2 years ago

Hi @ace-99 – glad to hear you find dartz useful!

While dartz includes a StateT monad transformer that can be used to achieve a State+Future effect stack, it currently won't yield a fully type safe solution and is a bit messy to use. I would instead recommend using Evaluation, which provides an Either+Reader+Writer+State+Future effect stack while retaining full type and stack safety. If you don't need all the effects provided by Evaluation, you can hide them using typedefs such as:

// Uses only the State and Future parts of Evaluation
typedef MyAction<A> = Evaluation<Unit, Unit, Unit, MyState, A>;

See https://github.com/spebbe/dartz/tree/master/example/interpreter and @ibcoleman's great example in #87 for intros to Evaluation usage.

Sadly, there's no equivalent of "do" or "for" notation currently and monadic binds therefore need to be explicit in the code. Using Evaluation and exploiting the associativity of monadic binds would however allow you to simplify and get rid of nesting in expressions such as the one in your example.

Hope that helped!

ace-99 commented 2 years ago

Thanks for the reply! I'll give the evaluation a try, would be a great exercise and take care of a few hurtles at once.