Functional Programming Self-Affirmations

Value of the article and repetition of “old” FP ideas

  • Some see the post as just rehashing well-known FP concepts better covered in books and established blogs.
  • Others argue many newer developers never saw the originals; re‑surfacing these ideas in compact form is useful and accelerates learning.
  • Several commenters explicitly praise list-style summaries of core FP principles with links for deeper dives.

Learning resources and FP concepts referenced

  • Recommended learning materials include Haskell-oriented books and classic posts on:
    • “Parse, don’t validate”
    • “Make illegal states unrepresentable”
    • “Errors as values”
    • “Functional core, imperative shell”
    • Smart constructors

Applying these ideas outside “pure” FP

  • One camp claims most principles can be implemented in mainstream imperative/OOP languages using: immutability, encapsulation, ADTs / sum types (or approximations), generics, wrappers, builders, and disciplined code review.
  • Skeptics argue some patterns rely heavily on FP features (type inference, monads, do-notation, expression orientation) and become awkward or fragile without syntactic and type-system support.

Errors as values vs exceptions

  • Strong support for “errors as values” in languages like Rust, Go, Zig, Odin; Rust’s Result, ?, and #[must_use] are cited as good ergonomics.
  • Concerns: returning error values can be silently ignored in imperative languages; exceptions better support “let it crash” behavior.
  • Others respond that compilers, annotations, or static analysis can enforce use, and that exceptions vs values is largely a presentation/ergonomics trade-off.

“Make illegal states unrepresentable” – benefits and limits

  • Advocates: encoding invariants in types reduces runtime checks, simplifies reasoning, and pushes complexity to compile time.
  • Critics: in complex or fast-changing domains (regulation-heavy, finance, configuration with many interdependent options) exhaustive type modeling can explode combinatorially and be expensive to maintain.
  • Counterpoint: if you truly have exponentially many meaningful states, the domain is inherently complex; enums/ADTs can be factored rather than listing all combinations, but there’s tension between strict modeling and evolvability.

Functional core, imperative shell and GUI/state

  • Widely liked for testability and limiting I/O and concurrency to boundaries.
  • Some note difficulties composing “pure core + impure shell” in GUI-style systems and large apps; global state stores (e.g., Redux-like) solve some issues but create others (hidden constraints, database-like complexity).

OOP, FP, and smart constructors

  • Several commenters stress that many “FP” ideas (smart constructors, invariants in constructors, sum types, visitor/Church encodings) are not exclusive to FP and can be emulated in OOP languages.
  • Debate continues over whether FP or OOP provides better tools for extensibility, live environments, and large-scale maintainability.