cyclops-integration icon indicating copy to clipboard operation
cyclops-integration copied to clipboard

How to use ReaderT

Open noorulhaq opened this issue 7 years ago • 10 comments

Can you please share any example of how to use ReaderT monad transformer like below Scala example gist?

https://gist.github.com/noorulhaq/d620f750eafb0e9cd8496ce99b52ac2e

The objective is to avoid extra map required for extracting value from Future.

noorulhaq avatar Jan 22 '17 13:01 noorulhaq

Hey @noorulhaq I haven't had time to look at this yet - I'll play around with it next week and see if it can be done with what is available in 1.x. Might have a few questions also :)

johnmcclean avatar Jan 28 '17 23:01 johnmcclean

I think the best thing to do is to use 2.x for this. I'm working on adding Kleisli impl directly there. There is a work in progress PR here if you want to take a look :- https://github.com/aol/cyclops-react/pull/510/files

It will include Kleisli & Cokleisli, also Coreader, Writer, State & ReaderWriterState aswell as a type-safe ReaderT implementation.

I will also add in For Comprehensions in a number of places.

  1. Functions class (for comps for working directly with j.u.Function)
  2. Fn1 (for comps for working with Fn1 which extends j.u.Function)
  3. Kleisli (for comps for Kleisli instances)
  4. ReaderT (for comps of ReaderT instances)

If ReaderT and Kleisli extend from Fn1 and j.u.Function then 1+2 would allow us to run a for comprehension across both or 3 /4 can be used in cases where we choose one over the other.

I would imagine a release with this in it would be ~2 weeks away, if that is ok for you?


In v1, I think you could use ReaderTValue (which drops the Future type, but still let's us know we got a value type) and then use the for comprehensions in For.Values

johnmcclean avatar Feb 05 '17 11:02 johnmcclean

The only issue I have is that I have to wait for the new release. But I hope you understand the necessity of it. As soon as you start to compose different monads the functional programming starts to become awkward. Especially cases where you want to compose Monadic effects having different dependencies. As an example, consider composing functions that use Reader monad but each one requires different repositories. I still could not find a better way of achieving this even in Scala. Let me know if you had experienced any such issue.

noorulhaq avatar Feb 05 '17 12:02 noorulhaq

hey @noorulhaq you can pull the Kleilsli impl from the PR into your own code and play around with it against the current v2 now if you like. I'll keep it updated and add for comps soon.

I definitely see the value of ReaderT / Kleisli when working with a nested stack of monads (even one layer inside a Reader can be gnarly). I'm not sure how it can help with composing functions with different inputs (I presume that different repos corresponds to different inputs) though @jbgi might be able to suggest something.

johnmcclean avatar Feb 06 '17 10:02 johnmcclean

Well, the reason I want to compose functions with different repositories is because I want to thread the composition into a single transaction context.

Thanks for directing me to Kleilsli implementation.

Waiting for @jbgi comment on repository concern.

noorulhaq avatar Feb 06 '17 12:02 noorulhaq

The flatMap on the Kleisli implementation has been improved and for comprehensions aded.

johnmcclean avatar Feb 06 '17 12:02 johnmcclean

A couple of ideas / questions -

Would something like a local function (https://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/ReaderWriterStateT.scala#L195) help? I think as long as the type of output extracted from the repositories matches the actual repository lookup could be abstracted away inside the function passed to local.

Or alternatively & a little bit hacky, could we make the core input type a Tuple and wrap the calls to the functions we are composing. Inside the wrapper extract the relevant repo before passing it on?

johnmcclean avatar Feb 06 '17 13:02 johnmcclean

Hey @noorulhaq is this example from Debasish Ghosh's Functional and Reactive Domain Modelling? Does the book also describe the wider challenge, and if yes any potential solutions? I think being able to leverage the patterns described in that book in Java would be a good goal for the cyclops / cyclops-react projects.

johnmcclean avatar Feb 07 '17 20:02 johnmcclean

Yes, you are right. The example is from Debasish book and that is what I am trying nowadays. I am trying to convert the examples from the book into Java, to demostrate how similar kind of functional style can be achieved in java. Unfortunately, the books does not give any description about this challenge. Infact transaction management is not even covered in the book.

noorulhaq avatar Feb 07 '17 20:02 noorulhaq

2.0.0-MI4 should be available on Maven Central. I think this is a rough equivalent of the Scala example

public class AccountService{
        public Kleisli<Witness.future,AccountRepository,Account> debit(String no, Amount amount){
            return repo -> Future.of ( ()-> debit account   ).anyM();
        }

        Kleisli<Witness.future,AccountRepository,Account> credit(String no, Amount amount){
            return repo -> Future.of (  ()->credit account   ).anyM();
        }
        public Kleisli<Witness.future,AccountRepository,Tuple2<Account,Account>> transfer(String from, String to,  Amount amount) {
          return debit(from,amount).forEach2(i->credit(to,amount),Tuple::tuple);

}

johnmcclean avatar Feb 16 '17 22:02 johnmcclean