Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use ReaderT #255

Open
noorulhaq opened this issue Jan 22, 2017 · 10 comments
Open

How to use ReaderT #255

noorulhaq opened this issue Jan 22, 2017 · 10 comments
Labels

Comments

@noorulhaq
Copy link

noorulhaq commented Jan 22, 2017

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.

@johnmcclean
Copy link
Member

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
Copy link
Member

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

@noorulhaq
Copy link
Author

noorulhaq commented Feb 5, 2017

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.

@johnmcclean
Copy link
Member

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.

@noorulhaq
Copy link
Author

noorulhaq commented Feb 6, 2017

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.

@johnmcclean
Copy link
Member

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

@johnmcclean
Copy link
Member

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
Copy link
Member

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.

@noorulhaq
Copy link
Author

noorulhaq commented Feb 7, 2017

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.

@johnmcclean
Copy link
Member

johnmcclean commented Feb 16, 2017

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);

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants