Hpas
Functional ADT And Asynchronous stuff in Java
Install / Use
/learn @Smallibs/HpasREADME
HiPeAS
Functional paradigm deeply drives the design with a taste of OO for encapsulation and chaining methods which mimics infix
operators like Haskell monad function >>=.
In addition, with version 21 of Java an Async/Await DSL like is available.
Since such ADT provides traditional map, flapmap etc. functions for a DSL perspective are also given in order to increase the code readability.
A taste of HiPeAS
Executor executor = ExecutorHelper.create(Executors.newSingleThreadExecutor());
Promise<String> helloWorldPromise = executor.async(() -> "Hello").and(s -> s + " world!");
HiPeAS overview
Synchronous data types
Basically well known MayBe and Try are available for this purpose. Theses ADT are also the basis for the asynchronous part
of this library.
Asynchronous computational model
Executors
Executor executor = ExecutorHelper.create(Executors.newSingleThreadExecutor());
async
In Executor <T> async :: (() -> T) → Promise<T>
Promise<Integer> integerPromise = executor.async(() -> 1);
await
In ExecutorHelper <T> await :: (Promise<T>, Duration) → Try<T>
Try<Integer> result = ExecutorHelper.await(integerPromise, Duration.TWO_SECONDS);
Promise
and or map
In Promise<T> <R> map :: (T → R) → Promise<R>
In Promise<T> <R> and :: (T → R) → Promise<R>
integerPromise.map(i -> i + 1);
integerPromise.and(i -> i + 1);
then or flatmap
In Promise<T> <R> flatmap :: (T → Promise<R>) → Promise<R>
In Promise<T> <R> then :: (T → Promise<R>) → Promise<R>
integerPromise.flatmap(i -> executor.async(() -> i + 1));
integerPromise.then(i -> executor.async(() -> i + 1));
Back to the Future
In Promise<T> getFuture :: () → Future<T>
integerPromise.getFuture();
Conclude on success
In Promise<T> onSuccess :: (T → void) → Promise<T>
integerPromise.onSuccess(i -> System.println(i))
Conclude on failure
In Promise<T> onFailure :: (Throwable → void) → Promise<T>
integerPromise.onFailure(t -> t.printStackTrace(System.err))
Conclude on complete
In Promise<T> onComplete :: (Try<T> → void) → Promise<T>
integerPromise.onComplete(t -> t.fold(integerPromise::onSuccess, integerPromise::onFailure));
Async Await DSL
Now we can use async/await mechanism using Loom virtual thread. We can now await for a promise implying an asynchronous mechanism based on thread parking if it's a virtual thread or a blocking procedure for system thread.
var executor = ExecutorHelper.create(Executors.newVirtualThreadPerTaskExecutor());
var aLongAddition = executor.async(() -> {
var firstInteger = executor.async(() -> /* do something */ 2);
Thread.sleep(3000); // Current thread do nothing during 3 seconds
var firstInteger = executor.async(() -> /* do something else */ 5);
return firstInteger.await() + secondInteger.await(); // Await force virtual thread parking
}).await(); // System thread waiting for the result
Functor, Applicative and Monad
In addition monadic approach is available for each ADT. As usual Monad ihnerits Applicative which inherits Functor.
Functor
In PromiseHelper functor<T> :: Promise<T> → Functor<T>
Functor<Promise, Integer, Promise<Integer>> p1 = functor(executor.async(() -> 1));
HK<Promise, Integer, Promise<Integer>> p2 = p1.map(i -> i + 1);
Applicative
In PromiseHelper applicative<T> :: Promise<T> → Applicative<T>
Applicative<Promise, Integer, Promise<Integer>> p1 = applicative(executor.async(() -> 1));
HK<Promise, Integer, Promise<Integer>> p2 = p1.apply(functor(executor.async(() -> i -> i + 1)));
Monad
In PromiseHelper monad<T> :: Promise<T> → Monad<T>
Monad<Promise, Integer, Promise<Integer>> p1 = monad(executor.async(() -> 1));
HK<Promise, Integer, Promise<Integer>> p2 = p1.flatmap(i -> executor.async(() -> i + 1));
CompletableFuture and Promise
In CompletableFutureHelper completableFuture<T> :: Promise<T> → CompletableFuture<T>
Executor executor = ExecutorHelper.create(Executors.newSingleThreadExecutor());
Promise<String> helloWorldPromise = executor.async(() -> "Hello").and(s -> s + " world!");
CompletableFuture<String> completable = CompletableFutureHelper.completableFuture(helloWorldPromise);
In CompletableFutureHelper promise<T> :: CompletableFuture<T> → Promise<T>
CompletableFuture<String> completable = CompletableFutureHelper.supplyAsync(() -> "Hello World");
Promise<String> helloWorldPromise = CompletableFutureHelper.promise(completable);
Releases
This library is available at Sonatype OSS Repository Hosting service and can be simply used adding the following dependency - for instance - to your pom project.
<dependency>
<groupId>org.smallibs</groupId>
<artifactId>hpas</artifactId>
<version>0.12.6</version>
</dependency>
About the library design
The library has been designed simulating High Order Type in Java and self type thanks to F-Bounded quantification polymorphism.
For more information follow this link.
License
Copyright (C)2016-2025 D. Plaindoux.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
