These are chat archives for ramda/ramda

10th
Mar 2016
Michael Hurley
@buzzdecafe
Mar 10 2016 00:30
another example: compare Haskell functor with OCaml functor.
Brad Compton (he/him)
@Bradcomp
Mar 10 2016 01:31
Do you guys accept tiny PRs to fix documentation?
Scott Christopher
@scott-christopher
Mar 10 2016 01:32
@Bradcomp absolutely :)
Brad Compton (he/him)
@Bradcomp
Mar 10 2016 01:34
:+1:
Nevermind, just saw somebody already got to it.
it seems relevant to R.toString
Keith Alexander
@kwijibo
Mar 10 2016 11:03
Do people use helper functions to deal with nested ADTs ? like some sort of deepMap function to map over the innermost value inside an arbitarily deep nesting of functors?
or is that the wrong way to go about things?
I'm wondering how best to map over (and potentially then fork) something that could be a Task(a) or a Left(error) or a Right(Task(a))
Nathan Ridley
@axefrog
Mar 10 2016 11:28
@scott-christopher you answered a question of mine back in early January, and I forgot I asked it... so, a belated thanks :D :point_up: January 2, 2016 10:09 PM
Scott Christopher
@scott-christopher
Mar 10 2016 11:30
:thumbsup: Hope it helped :)
Nathan Ridley
@axefrog
Mar 10 2016 11:31
i can't remember what i was doing at the time, but i guess i got there in the end :D
I want to ask a question that is both relevant to functional programming and streams-based programming (e.g. rxjs/most/bacon/etc. => IObservable) but am particularly interested in the functional perspective. I don't know how common it is for functional programmers to also have experience with stream libraries, but I'll ask anyway.

Imagine a function that you call which represents an intention to make a particular API request (but does not actually perform the execution itself). Effectively you're saying give me an object which packages up the details of an API request I'd like to make. You then dispatch that object via a stream, and somewhere down the line the request is consumed and executed. Now, imagine that this function not only packages up the details of the request to be made, but also exposes a freshly-created stream; the function is still referentially-transparent because a fresh stream is created every time, and it always has exactly the same characteristics. It's just an empty, non-terminated stream. The catch though is this: You're supposed to listen to the stream to get the results of the API request when it is eventually executed down the line. The stream is actually a subject- the consumer is going to take that subject and feed it the result, or results, of the API request, and then terminate the stream if/when the job is done (if ever). So... the initial function call made upstream is clean and functionally-pure, but it's probably going to drop that fresh stream into some other pipeline to be flatMapped, or whatever, in order to fold the result of the API request into the overall application flow. The request object returned by the function might look like this:

{ call: 'getStuff', args: ['foo', 'bar'], result$ }

What I want to know is does this make you, as a functional programmer, twitch? Does it raise any alarm bells, or feel wrong in some way, and if so, why?

kwijibo @kwijibo reads back to :point_up: March 5, 2016 9:45 PM, re handling nested datatypes
Ivan Demchenko
@raqystyle
Mar 10 2016 12:38
@axefrog imho and personally, I can't see any problem here. Probably, I'd separate functions what generate payload and stream from payload. But you're right, you can just flatmap streams into another stream. From my little experiense, it's rather good to have a functions that generate one thing and a function that maps that thing to another thing.
Nathan Ridley
@axefrog
Mar 10 2016 12:41
@raqystyle Thanks for the feedback; taking me a while to figure out which patterns I am happy with regarding functional/reactive programming. There doesn't seem to be a lot out there in terms of advice on best practices.
Ivan Demchenko
@raqystyle
Mar 10 2016 12:49
@axefrog same here. That's why I was recommended to read a book about and play with Haskell. Also, there is a number of projects (elm and purescript) that helped me out to make certain things clearer. But still, sometimes, I have the same questions: where to get the list of the best practices or problems-resolutions. I think, the problem here is that the veriety of usecases is so huge, that you can only percieve very abstract things and then come up with the solution for the particular problem. Thus, in your case, I think there's nothing wrong in flatMapping streams. As long as functions are pure it fine because it will be easier to refactor.
Nathan Ridley
@axefrog
Mar 10 2016 12:51
Yeah I think in the case I described, all that's really happening is I'm creating an efficient, context-specific portal to an external source which would have been available via the stream source anyway, except in this case you don't need to do any filtering to get at the result.
Risto Stevcev
@Risto-Stevcev
Mar 10 2016 19:09
@axefrog You might want to check out Futures or my LazyEither library, which works like Future but wraps things in the type safety of Either and won't execute the rest of the chain if the Either type is Left (error), and also doesn't need to use fork because it's encapsulated in the Either type (see this and this). It seems to me like you're describing that kind of solution.
Keith Alexander
@kwijibo
Mar 10 2016 21:24
@Risto-Stevcev LazyEither doesn't have fork but is .value() doing the same thing (triggering the actual computation)?
Risto Stevcev
@Risto-Stevcev
Mar 10 2016 22:47
@kwijibo Yeah, that's right. The key difference is that it doesn't resort to a pyramid of doom by having to split the result into two callbacks. You can bake in error handling or recovery into your pipeline
You could even use it to do some cleaner FRP because you can handle errors via the one pipeline
If you need to "fork" into two (or n) different callbacks then you still have that option, but the dev isn't forced into that situation