https://github.com/domix/dmx-fun
This repository contains a collection of implementations and experiments exploring functional programming constructions in Java.
https://github.com/domix/dmx-fun
functional-programming gradle java java-25 railway-oriented-programming
Last synced: 16 days ago
JSON representation
This repository contains a collection of implementations and experiments exploring functional programming constructions in Java.
- Host: GitHub
- URL: https://github.com/domix/dmx-fun
- Owner: domix
- License: apache-2.0
- Created: 2025-07-01T01:36:58.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-03-02T06:09:10.000Z (22 days ago)
- Last Synced: 2026-03-02T09:43:02.905Z (22 days ago)
- Topics: functional-programming, gradle, java, java-25, railway-oriented-programming
- Language: Java
- Homepage: https://domix.github.io/dmx-fun/
- Size: 2.88 MB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# λ dmx-fun: Functional Programming Constructions in Java

This repository contains a collection of implementations and experiments exploring **functional programming constructions in Java**. The goal is to demonstrate how functional paradigms—such as immutability, pure functions, higher-order functions, currying, and more—can be expressed in Java, a traditionally object-oriented language.
## 🔍 Purpose
While Java is not a purely functional language, modern features like lambda expressions, streams, and the `Optional` and `CompletableFuture` APIs allow for elegant and expressive functional-style programming. This project aims to:
- Explore functional programming principles in Java
- Showcase reusable constructions inspired by functional languages
- Experiment with Java libraries that support functional programming
- Serve as a reference and learning resource for developers
## 📦 What's Included
Examples and implementations may include:
- Function composition and higher-order functions
- Currying and partial application
- Immutable data structures
- Functional error handling (e.g., using `Try`, `Result`, or `Option`)
- Lazy evaluation
- Monads and functors (in a Java-friendly context)
- Functional streams and pipelines
## 🛠 Technologies
- Java 24+
- Gradle
- Spock for testing
- [Vavr](https://www.vavr.io/) or similar libraries for functional data types (optional)
## 🤝 Contributions
Contributions, discussions, and suggestions are welcome! Feel free to open issues or submit pull requests.
## 📄 License
This project is licensed under the Apache License. See the [LICENSE](./LICENSE) file for more details.
## 🛠️ Usage
### Installation
This library is available on Maven Central. To use it, include the following dependency to your project's configuration file:
#### Maven
```xml
codes.domix
fun
0.0.10
```
#### Gradle
```groovy
implementation("codes.domix:fun:0.0.10")
```
### Usage
Assuming you have imported the library, you can start using it in your code.
Let's start with a simple example. You have a method that validates a user's email, in a method like this:
```java
protected Result isValidEmail(
CreateUserCommand command
) {
var email = command.email();
if (email == null || email.isBlank()) {
return Result.err("Provided email is either null or blank");
}
boolean emailMatches = EMAIL_PATTERN
.matcher(email)
.matches();
if (!emailMatches) {
return Result.err("Invalid email");
}
return Result.ok(command);
}
```
In the previous example, we are using the `Result` type from the `fun` library. This type is a simple wrapper around an `Optional` that provides additional methods for handling errors.
In a nutshell, the `Result` type allows you to express a computation that may fail, and handle the error case in a type-safe way.
If everything goes well, the `Result` will contain the original value, in case of error, it will contain an error message.
Now you want to validate the user's password, with similar logic. You can create a new method like this:
```java
protected Result isValidPassword(
CreateUserCommand command
) {
var password = command.password();
if (password == null) {
return Result.err("Provided password is null");
}
boolean validPassword = PASSWORD_PATTERN
.matcher(password)
.matches();
if (!validPassword) {
return Result.err("Invalid password.");
}
return Result.ok(command);
}
```
As you can see, the `Result` type is used to express the result of the validation.
Now we can combine both validations in a single method. You can do it like this:
```java
public Result createUser(CreateUserCommand command) {
return this.isValidEmail(command)
.flatMap(this::isValidPassword)
.flatMap(this.userRepository::createUser);
}
```
In this case, the validation is performed in two steps, and the result of the first step is used as the input for the second step.
In the end, the result of the whole validation process is used to create the user in the database.
The main benefit of this approach is that the validation logic is encapsulated in a single method, and it can be reused in other places.