fp-ts: Functional Programming in TypeScript

repository·master·Indexed 11 days ago

https://github.com/gcanti/fp-ts

A library for typed functional programming in TypeScript providing core abstractions such as Monads, Functors, and specialized data types like Option and Either. Version 2.16.11 requires TypeScript 3.5+ and strict mode. The project is currently transitioning into the Effect-TS ecosystem, which is considered the successor (fp-ts v3).

Tokens
236.6K
Snippets
962
Records
1.2K
Agent score
94%

What's inside fp-ts

  1. Overview of fp-ts modules

    master

    The index.ts module serves as the primary entry point for fp-ts, organizing the library into several key categories:

    • Data Types: Concrete implementations of functional structures like array, either, option, task, reader, and more.
    • Models: Algebraic structures and type class implementations (e.g., functor, monad, applicative, semigroup) that define how data types behave.
    • Monad Transformers: Specialized wrappers for combining effects, such as eitherT, optionT, and taskE.
    • Utils: General purpose utility functions for boolean, date, json, string, and other primitives.

    This structure allows developers to compose complex functional programs by selecting the appropriate data types and applying mathematical models to them.

  2. What is fp-ts?

    master

    fp-ts is a library that provides popular patterns and reliable abstractions from typed functional languages (like Haskell, PureScript, and Scala) for use in TypeScript. It enables developers to write pure functional programming (FP) applications and libraries using higher-order abstractions.

    Note: The library assumes the user already understands functional programming concepts. It is not a teaching tool for FP.

  3. Explore the fp-ts Ecosystem

    master
    The fp-ts ecosystem consists of various tools, libraries, bindings, and plugins designed to extend functional programming capabilities in TypeScript. Developers can use these to bootstrap new libraries, extend core functionality (like optics, routing, or parsing), or integrate fp-ts with other reactive or web frameworks.
  4. What is ReaderT and how does it work?

    master

    The ReaderT monad transformer adds a read-only environment to an existing monad. It allows you to carry a shared context (an environment) through a sequence of computations.

    Key behaviors:

    • of: Creates a ReaderT that ignores the environment.
    • chain: Passes the inherited environment to both the current computation and the subsequent subcomputation, allowing for sequential operations that share the same context.
  5. What is TaskEither?

    master

    TaskEither<E, A> represents an asynchronous computation that either yields a value of type A or fails yielding an error of type E. It is essentially a Task<Either<E, A>>.

    Use TaskEither when you need to model asynchronous operations that can fail. If your asynchronous computation is guaranteed never to fail, use Task instead.

  6. What is a JoinSemilattice

    master

    A JoinSemilattice (or upper semilattice) is an algebraic structure defined by a join operation that acts as a least upper bound. To be a valid JoinSemilattice, the join operation must satisfy three mathematical laws:

    1. Associativity: a ∨ (b ∨ c) ↔ (a ∨ b) ∨ c
    2. Commutativity: a ∨ b ↔ b ∨ a
    3. Idempotency: a ∨ a ↔ a
  7. What is EitherT and how to use it

    master

    The EitherT is an error monad transformer. It is used to add error handling capabilities to other monads.

    Key operations:

    • of: Yields a successful computation.
    • chain: Sequences two subcomputations, automatically failing if the first one results in an error.
  8. What is a Ring

    master

    A Ring is a type that supports addition, multiplication, and subtraction operations. It extends the Semiring interface, meaning it inherits all Semiring laws and adds the requirement for an additive inverse.

    Additive Inverse Law: a - a <-> (zero - a) + a <-> zero

  9. What is a Functor?

    master

    A Functor is a type constructor that supports a mapping operation called map. This operation allows you to transform a function a -> b into a function f a -> f b, where f represents a computational context.

    To be a valid Functor, an instance must satisfy two laws:

    1. Identity: F.map(fa, a => a) <-> fa (mapping the identity function leaves the structure unchanged).
    2. Composition: F.map(fa, a => bc(ab(a))) <-> F.map(F.map(fa, ab), bc) (mapping a composed function is equivalent to mapping each function in the composition sequentially).
  10. What is FilterableWithIndex?

    master

    The FilterableWithIndex interface extends FunctorWithIndex and Filterable, providing methods to filter or partition a structure (like an Array or Option) using an index I. This index is passed to every predicate or mapping function, allowing for context-aware filtering (e.g., filtering an array based on its current index).

    It provides several core operations:

    • filterWithIndex: Filters elements based on a predicate that accepts the index.
    • filterMapWithIndex: Maps elements and filters out those that return None, using the index in the mapping function.
    • partitionWithIndex: Splits a structure into two based on a predicate.
    • partitionMapWithIndex: Splits a structure into two Separated structures by applying a function that returns an Either (using the index for context).
  11. What is a Semigroup and how does it work?

    master

    A Semigroup<A> is an abstraction for a type A that has an associative binary operation. Associativity means that for any x, y, and z, the order in which you group the operations does not change the result: concat(x, concat(y, z)) === concat(concat(x, y), z).

    A common example is a string where concat is the + operator.

    import { Semigroup } from 'fp-ts/Semigroup'
    
    const semigroupString: Semigroup<string> = {
      concat: (x, y) => x + y,
    }
    
    const x = 'x'
    const y = 'y'
    const z = 'z'
    
    semigroupString.concat(x, y) // 'xy'
    semigroupString.concat(x, semigroupString.concat(y, z)) // 'xyz'
    semigroupString.concat(semigroupString.concat(x, y), z) // 'xyz'