[HN Gopher] Show HN: FP-pack - Functional pipelines in TypeScrip...
       ___________________________________________________________________
        
       Show HN: FP-pack - Functional pipelines in TypeScript without
       monads
        
       Hi HN,  I built fp-pack, a small TypeScript functional utility
       library focused on pipe-first composition.  The goal is to keep
       pipelines simple and readable, while still supporting early exits
       and side effects -- without introducing monads like Option or
       Either.  Most code uses plain pipe/pipeAsync. For the few cases
       that need early termination, fp-pack provides a SideEffect-based
       pipeline that short-circuits safely.  I also wrote an "AI agent
       skills" document to help LLMs generate consistent fp-pack-style
       code.  Feedback, criticism, or questions are very welcome.
        
       Author : superlucky84
       Score  : 13 points
       Date   : 2026-01-03 15:00 UTC (8 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | superlucky84 wrote:
       | One thing I'd especially like feedback on is the SideEffect
       | approach.
       | 
       | It's intentionally not a monad, and I'm curious how others feel
       | about this trade-off compared to Option/Either in real-world
       | TypeScript codebases.
        
         | cobbal wrote:
         | Is early termination the only supported side effect? Its name
         | suggests a more general capability, but I didn't see more
         | examples in my (cursory) look at the readme
        
           | superlucky84 wrote:
           | Good question.
           | 
           | Early termination is the most common use case, but it's not
           | the only thing SideEffect represents. The name is
           | intentionally a bit broader -- it's meant to model "effects
           | where normal composition should stop".
           | 
           | In practice, that includes things like validation failures,
           | logging or notifications at pipeline boundaries, and error
           | reporting or metrics. That said, the scope is deliberately
           | conservative.
           | 
           | SideEffect isn't meant to be a general-purpose effect system.
           | If it were, it would quickly turn into something very close
           | to a monad or effect framework, which I'm intentionally
           | avoiding.
        
       | epgui wrote:
       | How is this not a monad? It might be trying really hard not to
       | reify the core concept of a monad, but it seems to me like it
       | ends up being essentially a complicated monad.
        
         | superlucky84 wrote:
         | It's definitely monad-adjacent.
         | 
         | The main difference is that SideEffect isn't a compositional
         | context -- there's no bind/flatMap, and composition
         | intentionally stops once it appears. It's meant as an explicit
         | early-exit signal in pipe-first code, not a general computation
         | container.
        
           | epgui wrote:
           | Is there any advantage whatsoever to this, as opposed to a
           | proper monad? I'm not seeing it.
           | 
           | The point of monads is that they solve this exact category of
           | problem in the simplest possible way.
        
             | superlucky84 wrote:
             | One more practical point is that a full monad doesn't fit
             | very naturally into a pipe-first interface.
             | 
             | Once you commit to a real monad, you need map/flatMap,
             | lifting, unwrapping, and rules about staying inside the
             | context across the whole pipeline. At that point, the pipe
             | abstraction stops being the primary mental model -- the
             | monad does.
             | 
             | SideEffect deliberately avoids that. It keeps the pipe
             | interface intact and only adds a single, explicit signal:
             | "stop here". That's why it's less powerful than a monad,
             | but also much simpler to integrate into existing pipe-based
             | code.
        
             | superlucky84 wrote:
             | fp-pack is also intentionally scoped for everyday frontend
             | developers.
             | 
             | It tries to borrow function composition and declarative
             | structure without requiring familiarity with full FP
             | abstractions like monads or effect systems.
        
       | eterps wrote:
       | While I like the concept, the side-effect pattern might be
       | difficult for the average developer to understand (without fp-
       | pack knowledge) in a shared codebase:
       | 
       | https://github.com/superlucky84/fp-pack?tab=readme-ov-file#s...
       | 
       | Still, this approach is very useful for most business logic, too
       | bad most programming languages don't provide a nice syntax for
       | this.
        
         | superlucky84 wrote:
         | That's a fair point, and I agree.
         | 
         | The SideEffect pattern is intentionally explicit, so without
         | fp-pack context it can look unfamiliar at first. The trade-off
         | is making early exits visible in the code, rather than hiding
         | them in conditionals or exceptions.
         | 
         | In practice, most code stays in plain pipe/pipeAsync.
         | SideEffect is meant for a small number of boundary cases only.
         | 
         | And I agree -- better language-level syntax for this kind of
         | pattern would make it much easier to adopt.
        
       | wk_end wrote:
       | The default any return type from pipelines is kind of brutal.
       | Seems like a real footgun. Is that fixable?
        
         | superlucky84 wrote:
         | That's a fair point -- it can definitely become a footgun if
         | you're not careful.
         | 
         | This happens because `runPipeResult` defaults its generic
         | parameter to `R = any`. When type safety matters, the intended
         | solution is to use `pipeSideEffectStrict`, which preserves all
         | possible SideEffect result types as a precise union throughout
         | the pipeline.
         | 
         | The default version prioritizes ergonomics and simplicity,
         | while the strict version prioritizes type safety.
         | 
         | Also, fp-pack is still in an early stage, so the usability and
         | API choices haven't been fully validated yet. That's why
         | feedback like this is especially helpful in shaping the
         | direction of the library.
        
       | almosthere wrote:
       | Every time I introduce something like this teams complain. RX is
       | a brain antipattern
        
         | superlucky84 wrote:
         | I really relate to that.
         | 
         | There's often a gap between what feels conceptually clean and
         | what teams are actually willing to carry cognitively. Rx in
         | particular tends to exceed that budget pretty quickly.
         | 
         | That's why fp-pack is intentionally narrow -- it's closer to
         | making a few control-flow cases explicit in pipe-first code
         | than introducing a broad new abstraction.
        
       | mrkeen wrote:
       | Haskell does not have nulls. Java 8 introduced Options, and now
       | there are nulls and Options.
       | 
       | Please tell me you didn't just add SideEffects to a language full
       | of side-effects.
        
         | superlucky84 wrote:
         | I understand the concern.
         | 
         | The intent isn't to add more side effects to an already side-
         | effectful language. It's closer to the opposite: trying not to
         | handle side effects all over the place, but to surface them as
         | part of a single, explicit flow.
         | 
         | This is less about adding something like Option to a language
         | without nulls, and more about making control-flow boundaries
         | visible in a multi-paradigm language where effects already
         | exist.
         | 
         | It's not an attempt to pretend the language is pure, just a
         | small step toward more declarative discipline.
        
       ___________________________________________________________________
       (page generated 2026-01-03 23:01 UTC)