{"action":"created","issue":{"url":"https://api.github.com/repos/aol/cyclops/issues/64","labels_url":"https://api.github.com/repos/aol/cyclops/issues/64/labels{/name}","comments_url":"https://api.github.com/repos/aol/cyclops/issues/64/comments","events_url":"https://api.github.com/repos/aol/cyclops/issues/64/events","html_url":"https://github.com/aol/cyclops/issues/64","id":114851299,"number":64,"title":"NoSuchElementException when flat-mapping Monad based on list","user":{"login":"smillies","id":8183111,"avatar_url":"https://avatars.githubusercontent.com/u/8183111?v=3","gravatar_id":"","url":"https://api.github.com/users/smillies","html_url":"https://github.com/smillies","followers_url":"https://api.github.com/users/smillies/followers","following_url":"https://api.github.com/users/smillies/following{/other_user}","gists_url":"https://api.github.com/users/smillies/gists{/gist_id}","starred_url":"https://api.github.com/users/smillies/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smillies/subscriptions","organizations_url":"https://api.github.com/users/smillies/orgs","repos_url":"https://api.github.com/users/smillies/repos","events_url":"https://api.github.com/users/smillies/events{/privacy}","received_events_url":"https://api.github.com/users/smillies/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-11-03T16:14:38Z","updated_at":"2015-11-03T21:04:23Z","closed_at":null,"body":"The following test fails with a NoSuchElementException while flatMapping. \r\n\r\n     @Test\r\n     public void test() {\r\n        List<Integer> list = Arrays.asList(1,2,3);\r\n        Monad<List<Integer>, Integer> m = Monad.of(list);\r\n        AnyM<Integer> any = m.anyM();\r\n        AnyM<Integer> mapped = any.flatMap(e -> any.unit(e));\r\n        List<Integer> unwrapped = mapped.asSequence().toList();\r\n        assertEquals(list, unwrapped);\r\n    }\r\n\r\nNow I'm aware that `Monad.of(list).anyM()` is a non-standard way of constructing a monad, using an internal API. However, think of the method as being parametrized by two type parameters E and M, such that I need to construct a monad with element type E and container type M. And of course `M e = ...; AnyM<S> any = AnyMonads.anyM(e);` won't compile.\r\n \r\nSo my questions are: 1) How can I generically construct a monad (e. g. based on M = Optional<E> or M = List<E>) without using an internal API. And 2) is there something wrong with my usage of `Monad` in the above test, or is it a bug?\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/aol/cyclops/issues/comments/153488188","html_url":"https://github.com/aol/cyclops/issues/64#issuecomment-153488188","issue_url":"https://api.github.com/repos/aol/cyclops/issues/64","id":153488188,"user":{"login":"johnmcclean-aol","id":9964792,"avatar_url":"https://avatars.githubusercontent.com/u/9964792?v=3","gravatar_id":"","url":"https://api.github.com/users/johnmcclean-aol","html_url":"https://github.com/johnmcclean-aol","followers_url":"https://api.github.com/users/johnmcclean-aol/followers","following_url":"https://api.github.com/users/johnmcclean-aol/following{/other_user}","gists_url":"https://api.github.com/users/johnmcclean-aol/gists{/gist_id}","starred_url":"https://api.github.com/users/johnmcclean-aol/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/johnmcclean-aol/subscriptions","organizations_url":"https://api.github.com/users/johnmcclean-aol/orgs","repos_url":"https://api.github.com/users/johnmcclean-aol/repos","events_url":"https://api.github.com/users/johnmcclean-aol/events{/privacy}","received_events_url":"https://api.github.com/users/johnmcclean-aol/received_events","type":"User","site_admin":false},"created_at":"2015-11-03T21:04:23Z","updated_at":"2015-11-03T21:04:23Z","body":"You have a few options that might help\r\n\r\nAsAnyM.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).\r\n\r\n     static <E, M> Function<E, AnyM<E>> extend(Function<E, M> lookup, Supplier<M> defaultValue) {\r\n         return s -> AsAnyM.convertToAnyM(Optional.ofNullable(lookup.apply(s)).orElseGet(defaultValue));\r\n     }\r\n\r\nI 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).\r\n\r\n\r\n# Writing your own Comprehender\r\n\r\nAll 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\r\n\r\nFor 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).\r\n\r\nComprehenders 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.\r\n\r\nhttps://github.com/aol/cyclops/blob/master/cyclops-monad-api/src/main/resources/META-INF/services/com.aol.cyclops.lambda.api.Comprehender\r\n\r\nIf 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).\r\n"}}