<p style="background-color: #38127C;">
<img
src="https://raw.githubusercontent.com/JKWA/funx/refs/heads/main/assets/images/funx-banner.jpg"
alt="Funx Banner"
height="120"/>
</p>
# Funx - Functional Programming Patterns for Elixir
[](https://github.com/JKWA/funx/actions/workflows/ci.yml)
[](https://hex.pm/packages/funx)
⚠️ **Beta:** Funx is in active development. APIs may change until version 1.0. Feedback and contributions are welcome.
**Official website:** [https://www.funxlib.com](https://www.funxlib.com)
**Code and API documentation:** [https://hex.pm/packages/funx](https://hex.pm/packages/funx)
## Installation
To use Funx, add it to the list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:funx, "~> 0.1.6"}
]
end
```
Then, run the following command to fetch the dependencies:
```bash
mix deps.get
```
## Usage Rules
Funx includes embedded **usage rules** in addition to API documentation.
They are written for development workflows assisted by LLMs.
➡️ [Browse Usage Rules](./lib/usage-rules.md)
## Equality
The `Eq` protocol defines how two values are compared, making equality explicit and adaptable to your domain.
- Define what “equal” means—compare by ID, name, or any derived attribute.
- Compose multiple comparisons—require all to match or just one.
- Implement for structs, built-in types, or custom comparators.
## Ordering
The `Ord` protocol defines ordering relationships in a structured way, without relying on Elixir’s built-in comparison operators.
- Define comparisons based on properties like size, age, or priority.
- Chain orderings to create fallback tiebreakers.
- Implement for any type, including custom structs.
## Monads
Monads encapsulate computations, allowing operations to be chained while handling concerns like optional values, failures, dependencies, or deferred effects.
- `Identity`: Wraps a value with no additional behavior—useful for organizing transformations.
- `Maybe`: Represents optional data using `Just` for presence and `Nothing` for absence.
- `Either`: Models computations with two possibilities—`Left` and `Right`.
- `Effect`: Encapsulates deferred execution with error handling, similar to `Task`.
- `Reader`: Passes an immutable environment through a computation for dependency injection or configuration.
- `Writer`: Threads a log alongside a result using any monoid—useful for tracing, reporting, or accumulating metadata during computation.
## Monoids
Monoids combine values using an associative operation and an identity element. They are useful for accumulation, selection, and combining logic.
- `Sum`: Adds numbers (`0` is the identity).
- `Product`: Multiplies numbers (`1` is the identity).
- `Eq.All`: Values are equal only if all comparators agree.
- `Eq.Any`: Values are equal if any comparator agrees.
- `Predicate.All`: All predicates must hold.
- `Predicate.Any`: At least one predicate must hold.
- `Ord`: Defines ordering compositionally.
- `Max` and `Min`: Select the largest or smallest value by custom ordering.
- `ListConcat`: Concatenates lists (`[]` is the identity).
- `StringConcat`: Concatenates strings (`""` is the identity).
## Predicates
Predicates are functions that return `true` or `false`. Funx provides combinators for composing them cleanly.
- `p_and`: Returns `true` if both predicates pass.
- `p_or`: Returns `true` if either predicate passes.
- `p_not`: Negates a predicate.
- `p_all`: Returns `true` if all predicates in a list pass.
- `p_any`: Returns `true` if any predicate in a list passes.
- `p_none`: Returns `true` if none pass.
## Folding
The `Foldable` protocol defines how to reduce a structure to a single result.
- `fold_l`: Reduces from the left, applying functions in order.
- `fold_r`: Reduces from the right, applying functions in reverse.
Useful for accumulating values, transforming collections, or extracting data.
## Filtering
The `Filterable` protocol defines how to conditionally retain values within a context.
- `guard`: Keeps a value if a condition is met; otherwise returns an empty context.
- `filter`: Retains values that satisfy a predicate.
- `filter_map`: Applies a transformation and keeps results only when the transformed value is present.
## Sequencing
Sequencing runs a series of monadic operations in order, combining the results.
- `concat/1`: Removes empty values and unwraps the present results from a list.
- `concat_map/2`: Applies a function to each element and collects only the present results.
- `sequence/1`: Converts a list of monadic values into a single monadic value containing a list. Short-circuits on the first failure or absence.
- `traverse/2`: Applies a function to each element and sequences the resulting monadic values.
- `sequence_a/1`: Applicative version of sequence—combines all and collects results.
- `traverse_a/2`: Applicative version of traverse—applies a function to each element and collects results.
## Lifting
Lifting functions promote ordinary logic into a monadic or contextual form.
- `lift_predicate/3`: Wraps a value in a monad if a condition holds; returns an empty or failed context otherwise.
- `lift_eq/1`: Adapts an `Eq` comparator to work within a monadic context.
- `lift_ord/1`: Adapts an `Ord` comparator to work within a monadic context.
## Interop
Funx integrates with common Elixir patterns like `{:ok, value}` and `{:error, reason}`.
- `from_result/1`: Converts a result tuple into a monadic context that distinguishes success from failure.
- `to_result/1`: Converts a monadic value back into a result tuple.
- `from_try/1`: Wraps a function call in a monad, capturing exceptions as failures.
- `to_try!/1`: Extracts the value from a monad or raises if it represents a failure.
## Documentation
The authoritative API documentation is published on [HexDocs](https://hexdocs.pm/funx).
## Contributing
1. Fork the repository.
2. Create a new branch for the feature or bugfix (`git checkout -b feature-branch`).
3. Commit changes (`git commit -am 'Add new feature'`).
4. Push the branch (`git push origin feature-branch`).
5. Create a pull request.
## License
This project is licensed under the MIT License.