Closed DrBoolean closed 7 years ago
I see compose as a “workflow builder”. The main, high level data flow of one’s application. Is that accurate?
I would say: compose is for declarative data flow, as opposed to the more imperative form where you take a function, call it, receive its result, then immediately pass that result into another function.
Would you agree? Or is there importance I'm missing here?
I totally agree with that and I find it very useful in a pure or non pure setting.
I suppose it was just a bit of a change to see it used as a "pretty useful utility" rather than the "model underpinning all pure program construction" :)
Without it, haskell programs would just be one big nested call. Functors/Monads wouldn't exist and so on.
As this is fp-lite, I'm not suggesting you push for an "all-composition" model or anything like that. I just wanted to share my perspective since it's such an important construct in pure fp.
Another chapter where the code is flawless and examples are clear. I'm writing my thoughts, but again, this is not as much a tech edit as it is an opinionated brain dump:
This was an interesting chapter where fp-lite vs fp-dark™ is concerned. In pure fp, compose is everything since, in a pure function, one can only ever pass output to the next input or it is lost. It is the only way to program; category theory is based entirely on it.
So in fp-lite, I’m trying to gauge its utility and purpose. After this chapter, I see
compose
as a “workflow builder”. The main, high level data flow of one’s application. Is that accurate? The last example does a very nice job of that.Anyways, I foresee some purist quibbles about compose should be mathematical function composition which is unary on its first argument too. That doesn’t matter much to me, but thought I’d mention it to save some angry reddit thread.
You did an amazing job of explaining
compose
and the candy factory was a spot on analogy (an oompa loompa song about impurity might have really driven it home…).I think people look to your writing specifically because you dive deep into topics and show the interworkings. So no criticism of the various implementation details.
“The slight performance advantage to pipe(..)” I’m concerned that line might give readers the impression that pipe() is always more performant and henceforth spawn an army of pipers over composers. But maybe not. In any case, it’s only more performant in our implementation, but not true in general.
Loved the abstraction stuff. Not sure if it’s worth a mention that, due to associativity, one can always “extract method” from a composition:
And lastly, pre-composing and post-composing via partialRight/partialLeft is rad. On top of this tower of abstractions, I’ve been using profunctors for that, which has the same effect, but comes with considerably more overhead.