# Changelog
## [0.8.0] - Unreleased
### Added
* Can now use DSL `Eq` and `Ord` in the Macro `eq_for` and `ord_for`
### Breaking Changes
* Ord DSL no longer adds default protocol tiebreaker. Instead, add it explicitly with `Ord.Protocol`:
```elixir
ord do
desc :name
asc Ord.Protocol
end
```
This makes the DSL more composable.
## [0.7.1] - Unreleased
### Added
* Exported .formatter to hex
## [0.7.0] - Unreleased
### Added
* `Funx.Validate` – A declarative DSL for building composable validators with optics-based field projection, applicative error accumulation, and identity preservation. Supports sequential and parallel modes, environment passing, and composable nested validators.
* `Funx.Validator` – Built-in validators for common validation patterns:
* `Required` – Presence validation (handles `Nothing` from Prism)
* `Email` – Email format validation
* `MinLength` / `MaxLength` – String length constraints
* `Pattern` – Regex pattern matching
* `Positive` / `Negative` – Numeric sign validation
* `Integer` – Integer type validation
* `GreaterThan` / `LessThan` / `GreaterThanOrEq` / `LessThanOrEq` – Numeric comparisons
* `In` / `NotIn` – Set membership validation
* `Range` – Numeric range validation
* `Each` – Collection item validation
* `Confirmation` – Field matching validation
* `Not` – Validator negation
### Breaking Changes
* Removed the import Either and import Maybe from the DSLs.
* Changed behavior for Either and Maybe to use Monad behaviours (not `run/3` and `run_maybe/3`)
## [0.6.1] - Unreleased
### Added
* `Funx.Predicate.DSL` – A declarative DSL for building boolean predicates with support for logical operators (`all`/`any`/`negate`), projections via optics or functions (`check`), and reusable validation modules.
## [0.6.0] - Unreleased
### Breaking Changes
**Module reorganization** for cleaner separation of protocols and utilities:
#### Eq Module Changes
* **`Funx.Eq` (protocol) → `Funx.Eq.Protocol`**
* The equality protocol is now `Funx.Eq.Protocol`
* Protocol implementations must use `defimpl Funx.Eq.Protocol, for: YourType`
* **`Funx.Eq.Utils` → `Funx.Eq`**
* Utility functions moved from `Funx.Eq.Utils` to `Funx.Eq`
* DSL merged into `Funx.Eq` (no more separate `Funx.Eq.Dsl`)
* `use Funx.Eq` imports the `eq` DSL macro
* `alias Funx.Eq` for utility functions (optional, or use fully qualified)
#### Ord Module Changes
* **`Funx.Ord` (protocol) → `Funx.Ord.Protocol`**
* The ordering protocol is now `Funx.Ord.Protocol`
* Protocol implementations must use `defimpl Funx.Ord.Protocol, for: YourType`
* **`Funx.Ord.Utils` → `Funx.Ord`**
* Utility functions moved from `Funx.Ord.Utils` to `Funx.Ord`
* DSL merged into `Funx.Ord` (no more separate `Funx.Ord.Dsl`)
* `use Funx.Ord` imports the `ord` DSL macro
* `alias Funx.Ord` for utility functions (optional, or use fully qualified)
#### Migration Guide
**Eq changes:**
```elixir
# Before
alias Funx.Eq.Utils
use Funx.Eq.Dsl
Utils.contramap(&(&1.age))
defimpl Funx.Eq, for: MyStruct do
def eq?(a, b), do: a.id == b.id
end
# After
use Funx.Eq # Imports eq DSL macro
alias Funx.Eq # For utility functions
Eq.contramap(&(&1.age))
defimpl Funx.Eq.Protocol, for: MyStruct do
def eq?(a, b), do: a.id == b.id
end
```
**Ord changes:**
```elixir
# Before
alias Funx.Ord.Utils
use Funx.Ord.Dsl
Utils.contramap(&(&1.score))
defimpl Funx.Ord, for: MyStruct do
def lt?(a, b), do: a.score < b.score
end
# After
use Funx.Ord # Imports ord DSL macro
alias Funx.Ord # For utility functions
Ord.contramap(&(&1.score))
defimpl Funx.Ord.Protocol, for: MyStruct do
def lt?(a, b), do: a.score < b.score
end
```
**Default parameter changes:**
* Functions with `ord \\ Ord` now use `ord \\ Funx.Ord.Protocol`
* DSL parser defaults to `Funx.Ord.Protocol` for comparison checks
### Rationale
This reorganization provides:
* Clear separation: Protocols (`*.Protocol`) vs utilities (`Funx.Eq`, `Funx.Ord`)
* Minimal imports: `use` imports only the DSL macro, not all functions
* Better discoverability: Main modules contain the utilities users interact with
* User control: Users decide whether to alias or use fully qualified names
## [0.5.0] - Unreleased
### Added
* `Funx.Optics.Traversal` – A composable optic for accessing multiple foci simultaneously. Supports filtering, combining multiple optics, and working with collections.
* `Funx.Ord.Dsl` – A declarative DSL for building custom ordering comparators with support for multiple projections, ascending/descending order, and automatic identity tiebreakers.
* `Funx.Eq.Dsl` – A declarative DSL for building equality comparators with support for projections, boolean logic (`all`/`any` blocks), and negation (`diff_on`).
### Breaking
* `Funx.List.maybe_head` renamed to `Funx.List.head/1` for consistency with `head!/1`. The function still returns `Maybe.t()` for safe head access.
## [0.4.2] - Unreleased
### Added
* `Funx.Optics.Iso` – A lawful isomorphism optic for reversible, lossless transformations between equivalent representations.
* `Funx.Maybe.Dsl` – A structured DSL for sequencing `Maybe` computations with explicit boundaries, validation, and side effects.
## [0.4.0] - Unreleased
### Added
Introduced **Optics** for composable, lawful data access and transformation:
* `Funx.Optics.Lens` - Total optic for required fields. Raises `KeyError` if focus is missing. Use for fields that should always exist.
* `Funx.Optics.Prism` - Partial optic for optional fields. Returns `Maybe`. Use for fields that may be absent or for selecting struct types.
* `Funx.Monoid.Optics.LensCompose` - Monoid wrapper for sequential lens composition
* `Funx.Monoid.Optics.PrismCompose` - Monoid wrapper for sequential prism composition
## [0.3.0] - Unreleased
### Added
Introduced a Funx.Tap protocol and migrated all monads to use protocol-based tap.
## Changed
tap implementations for Identity, Maybe, Either, Reader, and Effect now delegate through the Funx.Tap protocol.
## Breaking
Existing direct tap/2 implementations have been removed. Code relying on the previous module-specific tap implementations require updates.
## [0.2.3] - Unreleased
### Updated
* Refactored the Either DSL implementation to make it safer and easier to maintain.
## [0.2.2] - Unreleased
### Added
* Add `tap` behavior across Identity, Maybe, Either, Reader, and Effect Monads
* Add `tap` behavior to Either DSL
## [0.2.0] - Unreleased
### Added
* Either DSL for writing declarative error-handling pipelines with support for `bind`, `map`, `ap`, `validate`, and Either functions (`filter_or_else`, `or_else`, `map_left`, `flip`)
## Beta Status (v0.1.x)
⚠️ **Funx is in active development. APIs may change until version 1.0.**
We're currently in beta, focusing on:
* Core functionality implementation and stabilization
* Comprehensive usage rules and documentation for humans and LLMs
* Real-world testing and feedback incorporation
* API refinement based on practical usage patterns
**Current Status**: Feature-complete beta with comprehensive documentation. Ready for experimentation and feedback, but expect potential API changes before 1.0.
## Feedback Welcome
* 🐛 **Issues**: [Report bugs and suggest improvements](https://github.com/JKWA/funx/issues)
* 📖 **Documentation**: Help us improve usage rules and examples
* 🧪 **Real-world usage**: Share your experience using Funx in projects
* 💬 **Discussion**: Join conversations about functional programming patterns in Elixir
---
*Detailed changelog will begin with version 1.0. Until then, see [GitHub releases](https://github.com/JKWA/funx/releases) for version-specific changes.*