Comments (10)
The same thing happens with an empty list, i. e. constructed like this:
List<Integer> list = Collections.emptyList();
from cyclops-integration.
At the moment cyclops doesn't treat List as a full Monad (there is no reason why it can't, it just needs a specific Comprehender for List). What it does do is convert List to Stream in certain circumstances.
If you do this instead, your test will pass.
@Test
public void test() {
List<Integer> list = Arrays.asList(1,2,3);
Monad<Stream<Integer>, Integer> m = Monad.of(list.stream());
AnyM<Integer> any = m.anyM();
AnyM<Integer> mapped = any.flatMap(e -> any.unit(e));
List<Integer> unwrapped = mapped.asSequence().toList();
assertEquals(list, unwrapped);
}
Or alternative to avoid using Monad, you can use
AsAnyM.anyM(list);
AsAnyM provides an overloaded method that performs the conversion from List to Stream. But we should also add a native Comprehender for List also (feature enhancement).
from cyclops-integration.
I think neither alternative will work for me, because I don't know when I'm dealing with a list. It's only known at runtime. I'm trying to do something like this:
static <E, M> Function<E, AnyM<E>> extend(Function<E, M> lookup, Supplier<M> defaultValue) {
return s -> Monad.of(Optional.ofNullable(lookup.apply(s)).orElseGet(defaultValue)).anyM();
}
This code extends the given partial function to a total function and lifts the result to some monad. The element type is E, the container type would be M, if that were allowed. At runtime M might be Optional or List.
I'm trying to hide my internal use of Cyclops, so having clients using AnyM is out of the question.
Using Streams would also not work, because I can't put them in the lookup table behind the function, since they can be consumed only once. Switching everything to Suppliers would again appear arbitrary to my clients.
I guess a comprehender would do its work dynamically at runtime. Would it be difficult to write a List comprehender? Are there guidelines that I could follow if I wanted to try that myself? How is a custom comprehender activated?
from cyclops-integration.
You have a few options that might help
AsAnyM.convertToAnyM takes an Object as a parameter and does it's best to convert it into a supported Monad type (so List will become a Stream). E.g. this would wrap a Stream inside an AnyM when lookup returns a List (leaving Optional as Optional).
static <E, M> Function<E, AnyM<E>> extend(Function<E, M> lookup, Supplier<M> defaultValue) {
return s -> AsAnyM.convertToAnyM(Optional.ofNullable(lookup.apply(s)).orElseGet(defaultValue));
}
I don't know if this solves any traverse once issues you have with Stream (there is a Streamable construct that can lazily capture and replay the values of a Stream. It may actually make more sense if our Collection converter converted to it rather than the traverse once Stream (but it currently doesn't).
Writing your own Comprehender
All you need to do is implement this interface, and register it as JDK Service : https://github.com/aol/cyclops/blob/master/cyclops-monad-api/src/main/java/com/aol/cyclops/lambda/api/Comprehender.java
For List we would have to provide map & flatMap implementations, which at least initially could be done via stream() and map/flatMap followed by collect. (getTargetClass() should simply return List.class).
Comprehenders get picked up via the JDK Service Loader mechanism. There is a file in META-INF/services called com.aol.cyclops.lambda.api.Comprehender that details the implementations for a jar. You just add your new Comprehender implementation class there.
If you do write one, it would be great to see it submitted back! (If not I could write one - but I can also always help with any questions).
from cyclops-integration.
Thank you, convertToAnyM has been very helpful! When I have time, I might still try writing a Comprehender. Of course I'll let you know if I do.
Meanwhile, I have another question: I think it would be useful to have a uniform way to get back the type over which an AnyM was originally constructed. For example, when wrapping a List in AnyM, I'd expect unwrap()
to give me a List, but it doesn't, it gives me a SequenceImpl
. Thus I find myself writing utility functions like this:
static <E> Optional<E> unwrapOpt(AnyM<E> elem) {
return elem.unwrap();
}
static <E> List<E> unwrapList(AnyM<E> elem) {
return elem.asSequence().toList();
}
This isn't nice, because it leaks the existence of AnyM to my clients. Instead of unwrapList(myMethod()), I'd much rather define
<M,E> M myMethod() {
AnyM<E> elem = ...
return elem.unwrap();
}
I guess that AnyM just doesn't remember what object type was used to construct it.
BTW: I fear a GitHub issue may not be the appropriate forum to discuss such things. Should I direct my questions someplace else?
from cyclops-integration.
Here is fine, but there is also a GitHub chat room if you prefer.
AnyM.unwrap should return whatever the Monad type currently is. Because we don't have a Comprehender for List it gets converted into a Stream (in fact a cyclops.SequenceM which extends Stream, and SequenceImpl implements SequenceM). If we add the List comprehender we can also make sure the CollectionConverter does not to convert Lists to Streams (SequenceM in practice). That way AnyM.unwrap would always return a List in your case.
I'll add a specific issue for a List Comprehender.
from cyclops-integration.
By the way, you can write utility functions that will safely unwrap to any type (there are built in ones for Optional, Sequence / Stream and CompletableFuture). Your optional example would fail if the AnyM didn't wrap an Optional, but this should always work :-
static <E> Optional<List<E>> unwrapOpt(AnyM<E> elem) {
return elem.toOptional();
}
If elem was originally an Optional with a single value it will now be an Optional with that value wrapped in a List. If elem was a List, that List will be embedded in our Optional.
from cyclops-integration.
Thanks for explaining that. I didn't see that SequenceImpl was just a Stream. So the client can pass in a lookup function that yields a list, and must remember to manually collect(toList())
in the end. I just need to document that bit of behaviour. And once there's a List comprehender, things will be simpler. When do you think the 6.1.0 milestone will be reached?
from cyclops-integration.
Should have something available within the next week.
from cyclops-integration.
Released
from cyclops-integration.
Related Issues (20)
- Add Vavr Semigroups and Monoids HOT 1
- Move conversion methods into Companion classes
- Create a version of ReactiveSeq that is backed by Reactor Flux HOT 1
- Add support for RxJava2 HOT 1
- Operator interop between cyclops-react, Reactor and RxJava HOT 1
- How to re-throw exception? HOT 2
- Vavr value adapaters should implement ValueAdapter HOT 1
- Add coproduct factory methods HOT 1
- optional operator misspelt in Vavr Eithers companion class
- Add stack-safe lazy foldRight operator for vavr Streams HOT 1
- Add a module for Capsule
- Different behaviour in withCatch & runWithCatch methods HOT 1
- [Code quality] Inconsistence on coding styles. Use of .editorconfig HOT 1
- Upgrade to Cyclops X (10) HOT 1
- Create a cyclops-jackson-integration module
- Q: Is it possible to use try in an exception handler? HOT 1
- Missing integration modules and broken links in docs HOT 1
- Check and use an option HOT 1
- Use a finally HOT 2
- Jackson integration module incompatible with Jackson > 2.10.5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cyclops-integration.