aol/cyclops

Maximum number of levels in Do notation?

smarijic opened this issue · 4 comments

Hi,
I am trying to find out can I write transformation with Do notation with more then 5 levels, for example:

Do.forEach(TryInstances::monad)
    .__(this::first)
    .__(this::second)
    .__(this::third)
    .__(this::fourth)
    .__(this::fifth)
    .__(this::sixt)
    .yield(this::yieldResult)
    .fold(fn);

And also is it possible to replace results from this::first and this::second with result of this::third?

Thanks.

Hi @smarijic,

We will need to make code enhancements to add more levels to the Do notation. There is no reason why this can't be done (it just requires engineering effort). It would involve creating a new inner class D6 (and so on) and some tests. We can add expansion to 8 tiers to the 10.4.0 release.

If you explicitly define a lambda you can choose which parameters to pass on / replace / swap, at each stage. It's not as neat as a method reference but it should allow you to get the flexibility you need. And you only have to do it, when you want to make a change.

Option<Integer> res = Do.forEach(OptionInstances::monad)
                        ._of(10)
                        .__(i->some(i/2))
                        .__((a,b)->some(a-b-3))
                        .__((a,b,c)->some(a-c-b-2))
                        .__((a,b,c,d)->some(a+b+c+d+82))
                         .yield((a,b,c,d,e)->a+b+c+d+e)
                        .fold(Option::narrowK);

There are also some selectors on the Function interfaces that allow us to narrow a multi-parameter Function to a lower parameter one. E.g. on Function4 we can use Function4.___14 to select the first and last parameters to pass through to a BiFunction.

import static cyclops.function.Function2._1;
import static cyclops.function.Function2._2;
import static cyclops.function.Function3.*;
import static cyclops.function.Function4.*;

Option<Integer> res = Do.forEach(OptionInstances::monad)
                        ._of(10)
                        .__(i->some(i/2))
                        .__(_2(b->some(b-3)))
                        .__(__12((a,b)->some(a-b-4)))
                        .__(___12((a,b)->some(a+b+85)))
                        .yield((a,b,c,d,e)->a+b+c+d+e)
                        .fold(Option::narrowK)

There are some examples in the tests : https://github.com/aol/cyclops/tree/master/cyclops-pure/src/test/java/cyclops/typeclasses. But feel free to post up more details / questions here (especially if I have misunderstood or not covered what you were asking)

Hi @johnmcclean,
Thanks for fast response.

I have created PR for do notation up to Do8, not sure if I missed anything (except tests).
#1052

Great thanks @smarijic!

Merged