Official website: https://www.funxlib.com Code and API documentation: https://hex.pm/packages/funx
If you're upgrading from 0.6.0 or earlier, be aware of the module reorganization:
# Change protocol implementations
defimpl Funx.Eq, for: MyStruct # Old
defimpl Funx.Eq.Protocol, for: MyStruct # New
# Change imports and aliases
alias Funx.Eq.Utils # Old
use Funx.Eq.Dsl # Old
use Funx.Eq # New (imports eq DSL macro)
alias Funx.Eq # New (for utility functions)
# Example usage
Eq.contramap(&(&1.age))# Change protocol implementations
defimpl Funx.Ord, for: MyStruct # Old
defimpl Funx.Ord.Protocol, for: MyStruct # New
# Change imports and aliases
alias Funx.Ord.Utils # Old
use Funx.Ord.Dsl # Old
use Funx.Ord # New (imports ord DSL macro)
alias Funx.Ord # New (for utility functions)
# Example usage
Ord.contramap(&(&1.score))See the CHANGELOG for more details.
To use Funx, add it to the list of dependencies in mix.exs:
def deps do
[
{:funx, "~> 0.6"}
]
endThen, run the following command to fetch the dependencies:
mix deps.getFunx includes embedded usage rules in addition to API documentation.
They are written for development workflows assisted by LLMs.
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.
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.
The Ord module includes a DSL for building custom ordering comparators declaratively:
use Funx.Ord
user_ord = ord do
desc :priority
asc :name
desc :created_at
end
Enum.sort(users, Funx.Ord.comparator(user_ord))Features:
- Multiple projections with
ascanddescdirections - Automatic identity tiebreaker for deterministic ordering
- Support for optics (Lens, Prism), functions, and modules
- Ord variables for composing and reversing orderings
The Eq module includes a DSL for building equality comparators with boolean logic:
use Funx.Eq
contact_eq = eq do
on :name
any do
on :email
on :username
end
end
Funx.Eq.eq?(user1, user2, contact_eq)Features:
on- Field must be equaldiff_on- Field must differ (non-equivalence constraint)allblocks - All checks must pass (AND logic)anyblocks - At least one check must pass (OR logic)- Support for optics, functions, and custom comparators
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 usingJustfor presence andNothingfor absence.Either: Models computations with two possibilities—LeftandRight.Effect: Encapsulates deferred execution with error handling, similar toTask.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.
The Either monad includes a DSL for writing declarative pipelines that handle errors gracefully:
use Funx.Monad.Either
either user_id do
bind fetch_user()
bind validate_active()
map transform_to_dto()
endSupported operations:
bind- for operations that return Either or result tuplesmap- for transformations that return plain valuesap- for applying a function in an Either to a value in an Eithervalidate- for accumulating multiple validation errors- Either functions:
filter_or_else,or_else,map_left,flip,tap
Formatter Configuration: Funx exports formatter rules for clean DSL formatting. Add :funx to import_deps in your .formatter.exs:
[
import_deps: [:funx],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]See FORMATTER_EXPORT.md for details.
Optics provide composable, lawful abstractions for focusing on and transforming parts of data structures.
Lens: Total optic for required fields—raises if focus is missing. Use for fields that should always exist.Prism: Partial optic for optional fields—returnsMaybe. Use for fields that may be absent or for selecting struct types.Traversal: Optic for accessing multiple foci simultaneously. Use for filtering collections, combining multiple optics, or working with list-like structures.Iso: Total optic for reversible representation changes. Use when two shapes carry the same information and you need guaranteed round trip conversion (viewthenreview).
Monoids combine values using an associative operation and an identity element. They are useful for accumulation, selection, and combining logic.
Sum: Adds numbers (0is the identity).Product: Multiplies numbers (1is 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.MaxandMin: Select the largest or smallest value by custom ordering.ListConcat: Concatenates lists ([]is the identity).StringConcat: Concatenates strings (""is the identity).
Predicates are functions that return true or false. Funx provides combinators for composing them cleanly.
p_and: Returnstrueif both predicates pass.p_or: Returnstrueif either predicate passes.p_not: Negates a predicate.p_all: Returnstrueif all predicates in a list pass.p_any: Returnstrueif any predicate in a list passes.p_none: Returnstrueif none pass.
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.
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 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 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 anEqcomparator to work within a monadic context.lift_ord/1: Adapts anOrdcomparator to work within a monadic context.
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.
The authoritative API documentation is published on HexDocs.
- Funx Blog Posts - Articles and tutorials about using Funx, including deep dives into the Either DSL and functional programming patterns in Elixir
- Fork the repository.
- Create a new branch for the feature or bugfix (
git checkout -b feature-branch). - Commit changes (
git commit -am 'Add new feature'). - Push the branch (
git push origin feature-branch). - Create a pull request.
This project is licensed under the MIT License.
