3 ms·
Threading aka chaining aka composing. You describe a pipeline and then send a whole value through it, thus avoiding the naming of intermediate results. Function
by mbrock 11y ago
Threading aka chaining aka composing. You describe a pipeline and then send a whole value through it, thus avoiding the naming of intermediate results. Functional programmers call it "point-free style." It can't save you from naming in general, since each piece of your pipeline will be named, but it saves you from naming "variables."
Here is an example of the main part of a Haskell program (using the "pipes" combinators). It starts two concurrent pipelines. One reads user commands from a queue, encodes them, then writes them to an AMQP server. The other reads results from the AMQP server and runs them through a more complicated pipeline, the details of which aren't very interesting.
runEffectsConcurrently
(contents commandQueue >-> encoder >-> writeTo amqp)
(readFrom amqp >-> decoder
>-> skipEmpty
>-> logToFile
>-> forever (decodeMsg state)
>-> toChannel eventQueue)
What I like about this style has to do with how it avoids naming intermediate results. Instead of stuff like loops, anonymous callback functions, and variables, it approaches a declarative specification of the program's structure & behavior. I still had to give names to each component, but I didn't need to come up with names for the values that flow through the pipelines.
- king_magic 11y agoYeah, that makes sense. The author's terminology/wording wasn't clear/helpful IMO. Beyond that, though - the above code looks great - until you need to debug it. Personally, I'd rather pay a 'naming tax' on things for the sake of readability / debugability over what the original author is shooting for any day.
- mbrock 11y agoI haven't needed to debug it very much. Thankfully, it's easy to insert debugging helpers at any stage of the pipeline.
- king_magic 11y agoInteresting, maybe I'm just less familiar with debugging in Haskell.
- mbrock 11y agoThis is kind of a special scenario since what's described in the pipeline is already an I/O action, which makes it easy to insert logging anywhere (e.g., a "tap" component that prints its input and output w/ timestamp). Such pipelines aren't necessarily made up of I/O actions though; they can also be pure computations, which cannot perform side-effects such as logging. In that case, you can still insert debugging helpers, but you might need to be slightly creative. For example, if your pipeline generates a list of values, you could put debugging entries into that list. Generally, though, the saving grace in such a case is that each component will be a pure transformation, which means that you can easily call it with a test input and inspect the output. There are some step-by-step debugging tools for Haskell, but I haven't used them, and Haskell programmers mostly seem uninterested in that way of debugging. It doesn't fit very well with Haskell's evaluation model anyway. When I work with Haskell, I just debug in a different way, focusing on verifying correctness of functions and their combinations.
- codygman 11y ago> There are some step-by-step debugging tools for Haskell, but I haven't used them, and Haskell programmers mostly seem uninterested in that way of debugging. It doesn't fit very well with Haskell's evaluation model anyway. When I work with Haskell, I just debug in a different way, focusing on verifying correctness of functions and their combinations. I created hs-scrape[0] to write web scrapers and I frequently use the ghci debugger[1] for step-by-step debugging. 0: https://github.com/codygman/hs-scrape/ https://github.com/codygman/hs-scrape/ 1: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci-debugger.html https://downloads.haskell.org/~ghc/latest/docs/html/users_gu...
- KingMob 11y agoThe post was for Clojure Gazette, and all Clojure programmers would be familiar with the threading functions. I have to say, minimizing intermediate holding names makes debugging and writing clear code much easier. 97% of the time, I never miss the "naming tax".