diff --git a/.travis.yml b/.travis.yml
index bbe5966b..2fb30bf7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,29 +4,28 @@ sudo: false
language: java
jdk:
- - openjdk10
- - openjdk-ea
+ - openjdk8
matrix:
+ fast_finish: true
include:
- - jdk: openjdk11
- script:
- - ./gradlew build coverage -s -i
- after_success:
- - bash <(curl -s https://codecov.io/bash)
- - '[ "$TRAVIS_BRANCH" = "series/5.x" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ]
- && ./gradlew uploadArchives'
allow_failures:
- - jdk: openjdk10
- - jdk: openjdk-ea
script:
- - ./gradlew clean test
-
+ - ./gradlew build --no-daemon
env:
global:
- secure: Bun+1FZ29Q3dR9gZ/5brxcSf+zcY5tWrsqOA4GUb5bYCMyORuXQB0FYXuhKR4wB1pFrk1a9EYwRwSu3GwRJVWb+UzF0CNOWF/QG5tGPx32IOXScwlL/KonI4Vhs7Oc0fF4Wdb7euNrT27BU61jbUugjJ642b3n0VBYFYDdquprU=
- secure: QAxhjqLRa+WHKIzgIJPZ/rM5a5uzqG7E5rsC0YvB25cO712oYXmzsYPia/oSp0chXlYLYMfk2UnLeQCSx2e6ogXRRRa977Q+B33Nt0Hd9SGLtduv6DBrbA2ehLU12Ib4DWe5VhF5eueAunycYcllTvqA5h+pzTtEVbd68ZHncM4=
+
+before_cache:
+ - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
+ - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+
+cache:
+ directories:
+ - $HOME/.gradle/caches/
+ - $HOME/.gradle/wrapper/
diff --git a/ChangeLog.md b/ChangeLog.md
deleted file mode 100644
index 24276f35..00000000
--- a/ChangeLog.md
+++ /dev/null
@@ -1,33 +0,0 @@
-4.8
----
-
-### Enhancements
-
-- Enable upload of snapshot artifacts. (see [`e834e8b`](https://github.com/functionaljava/functionaljava/commit/e834e8b));
-- Add append methods to all Px classes. Fix #326 (see [`065ed43`](https://github.com/functionaljava/functionaljava/commit/065ed43));
-- Introduce the Eval monad (see [`98294fc`](https://github.com/functionaljava/functionaljava/commit/98294fc));
-- Fluent Equal/Ord construction (see [#333](https://github.com/functionaljava/functionaljava/pull/333));
-- Implement Zipper Eq and Hash and add tests (see [#343](https://github.com/functionaljava/functionaljava/pull/343));
-- Implement Vector equals (see [#350](https://github.com/functionaljava/functionaljava/pull/350));
-
-### Fixes
-
-- Fixed a bug in the NonEmptyList Semigroup implementation that resulted in the same NonEmptyList appended to itself. (Regression in 4.7, see [`07f94fa`](https://github.com/functionaljava/functionaljava/commit/07f94fa));
-- Fixes #334: exception in Either.LeftProjection.traverseIO (see [#335](https://github.com/functionaljava/functionaljava/pull/335));
-
-### Internal
-
-- Added Scalacheck Arbitrary implementations for Natural and NonEmptyList. (see [`405c3ec`](https://github.com/functionaljava/functionaljava/commit/405c3ec));
-- Added unit test coverage for Semigroup implementations. The StringBuffer and StringBuilder tests fail because both of those types are mutable. The IO test fails because the ArbitraryIO implementation does not implement equals. (see [`ef81130`](https://github.com/functionaljava/functionaljava/commit/ef81130));
-- Fixed the ArbitraryIO implementation and created a Properties object for testing the IO semigroup. (see [`a8e979f`](https://github.com/functionaljava/functionaljava/commit/a8e979f));
-- Added working tests coverage for the StringBuffer and StringBuilder semigroup implementations. Added the Semigroup tests to the list of Scalacheck test suite. (see [`aa4de33`](https://github.com/functionaljava/functionaljava/commit/aa4de33));
-- Equal: remove reference to static field of LazyString. Fix #321 (see [`6c6dabd`](https://github.com/functionaljava/functionaljava/commit/6c6dabd));
-- Add IOFunctions tests (see [#340](https://github.com/functionaljava/functionaljava/pull/340));
-- Add Stream tests (see [#341](https://github.com/functionaljava/functionaljava/pull/341));
-- Add tests for Try, F, FW, Digit (see [#346](https://github.com/functionaljava/functionaljava/pull/346));
-- Add Vector tests (see [#347](https://github.com/functionaljava/functionaljava/pull/347));
-- Add Optic tests (see [#348](https://github.com/functionaljava/functionaljava/pull/348));
-- Add Parser tests (see [#349](https://github.com/functionaljava/functionaljava/pull/349));
-- Add FingerTree tests (see [#351](https://github.com/functionaljava/functionaljava/pull/351));
-- Add TreeZipper tests (see [#352](https://github.com/functionaljava/functionaljava/pull/352));
-- Add Reader/Writer tests (see [#353](https://github.com/functionaljava/functionaljava/pull/353));
\ No newline at end of file
diff --git a/README.adoc b/README.adoc
index a7e2d3a4..ecf403e2 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,6 +1,6 @@
= Functional Java
-image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"]
+image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://app.travis-ci.com/github/functionaljava/functionaljava"]
image:https://codecov.io/gh/functionaljava/functionaljava/branch/master/graph/badge.svg["Code Coverage", link="https://codecov.io/gh/functionaljava/functionaljava"]
image:https://badges.gitter.im/functionaljava/functionaljava.svg[link="https://gitter.im/functionaljava/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
@@ -8,7 +8,7 @@ image::http://www.functionaljava.org/img/logo-600x144.png[]
Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language.
-The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 6 to 8.
+The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module.
Functional Java provides abstractions for the following types:
@@ -22,8 +22,9 @@ Important URLs for the project are:
* Website, http://www.functionaljava.org
* Website repository, http://github.com/functionaljava/functionaljava.github.io
-* Travis continuous integration build, https://travis-ci.org/functionaljava/functionaljava
-* Sonatype Repository, https://oss.sonatype.org/content/groups/public/org/functionaljava/
+* Travis continuous integration build, https://app.travis-ci.com/github/functionaljava/functionaljava
+* Sonatype repository, https://oss.sonatype.org/content/groups/public/org/functionaljava/
+* Maven Central repository, https://mvnrepository.com/artifact/org.functionaljava/functionaljava
== Downloading
@@ -31,16 +32,15 @@ The recommended way to download and use the project is through your build tool.
The Functional Java artifact is published to Maven Central using the group `org.functionaljava` with three published artifacts:
-* the core library (`functionaljava` or `functionaljava_1.8` if you use Java 8+)
-* Java 8 specific support (`functionaljava-java8`)
-* property based testing (`functionaljava-quickcheck` or `functionaljava-quickcheck_1.8` if you use Java 8+)
+* the core library (`functionaljava`)
+* property based testing (`functionaljava-quickcheck`)
+* a small amount of Java 8 support (`functionaljava-java-core`)
-The latest stable version is `4.8`. This can be added to your Gradle project by adding the dependencies:
+The latest stable version is `5.0`. This can be added to your Gradle project by adding the dependencies:
----
-compile "org.functionaljava:functionaljava:4.8"
-compile "org.functionaljava:functionaljava-java8:4.8"
-compile "org.functionaljava:functionaljava-quickcheck:4.8"
-compile "org.functionaljava:functionaljava-java-core:4.8"
+compile "org.functionaljava:functionaljava:5.0"
+compile "org.functionaljava:functionaljava-quickcheck:5.0"
+compile "org.functionaljava:functionaljava-java-core:5.0"
----
and in Maven:
@@ -48,34 +48,27 @@ and in Maven:
org.functionaljava
functionaljava
- 4.8
-
-
- org.functionaljava
- functionaljava-java8
- 4.8
+ 5.0
org.functionaljava
functionaljava-quickcheck
- 4.8
+ 5.0
org.functionaljava
functionaljava-java-core
- 4.8
+ 5.0
----
== Building
-FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 6 bytecode. This requires access to both JDK 6 and 8. The build system requires the environment variables `JAVA6_HOME` and `JAVA8_HOME` to refer to the appropriate directories.
-
-Building is done using Gradle 2.13. In the root directory run:
+Building is done using Java 8 and Gradle 7.4. In the root directory run:
----
./gradlew
----
-This requires access to Java and will download the Gradle build tool and necessary dependencies and build FunctionalJava.
+This requires access to Java 8 and will download the Gradle build tool and necessary dependencies and build FunctionalJava.
== Features
@@ -122,3 +115,7 @@ A more complete description of the features mentioned above are:
== License
link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause license) available at https://en.wikipedia.org/wiki/BSD_licenses[].
+
+== Release Notes
+
+For release notes for each version, see the directory link:etc/release-notes.
diff --git a/build.gradle b/build.gradle
index c070903d..c89c9536 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,30 +1,27 @@
defaultTasks 'build'
-ext {
-}
+apply plugin: "com.github.ben-manes.versions"
buildscript {
- ext {
- uptodateVersion = "1.6.3"
- }
-
repositories {
mavenLocal()
- jcenter()
mavenCentral()
+ gradlePluginPortal()
}
dependencies {
- classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion"
+ classpath "com.github.ben-manes:gradle-versions-plugin:0.42.0"
+ classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:6.1.0"
}
wrapper {
- gradleVersion = "4.10.2"
+ gradleVersion = "7.4"
distributionType = Wrapper.DistributionType.ALL
}
}
+
if (JavaVersion.current().isJava8Compatible()) {
allprojects {
tasks.withType(Javadoc) {
@@ -38,20 +35,21 @@ allprojects {
apply plugin: "jacoco"
jacoco {
- toolVersion = "0.8.2"
+ toolVersion = "0.8.7"
}
defaultTasks "build"
ext {
isSnapshot = true
- fjBaseVersion = "5.0"
+ fjBaseVersion = "5.1"
snapshotAppendix = "-SNAPSHOT"
fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "")
- fjConsumeVersion = "4.8"
+ fjConsumeVersion = "5.0"
signModule = false
+ uploadModule = false
projectTitle = "Functional Java"
projectName = "functionaljava"
@@ -61,23 +59,32 @@ allprojects {
projectUrl = "http://functionaljava.org/"
scmUrl = "git://github.com/functionaljava/functionaljava.git"
scmGitFile = "scm:git@github.com:functionaljava/functionaljava.git"
+ scmSshGitFile = "scm:git:ssh://git@github.com/functionaljava/functionaljava.git"
+ licenseUrl = "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE"
+ licenseName = "The BSD3 License"
+
+ issueUrl = "https://github.com/functionaljava/functionaljava/issues"
+ githubUrl = "https://github.com/functionaljava/functionaljava"
sonatypeBaseUrl = "https://oss.sonatype.org"
sonatypeSnapshotUrl = "$sonatypeBaseUrl/content/repositories/snapshots/"
sonatypeRepositoryUrl = "$sonatypeBaseUrl/content/groups/public"
sonatypeReleaseUrl = "$sonatypeBaseUrl/service/local/staging/deploy/maven2/"
+
sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl
+
primaryEmail = "functionaljava@googlegroups.com"
- dependencyJunit = "org.junit.vintage:junit-vintage-engine:5.2.0"
+ junitCompile = "junit:junit:4.13.2"
+ junitRuntime = "org.junit.vintage:junit-vintage-engine:5.8.2"
displayCompilerWarnings = true
+ generateTestReports = false
}
repositories {
- jcenter()
- mavenCentral()
mavenLocal()
+ mavenCentral()
}
version = fjVersion
@@ -90,32 +97,38 @@ subprojects {
buildscript {
repositories {
+ mavenLocal()
mavenCentral()
}
}
apply from: "$rootDir/lib.gradle"
- apply plugin: "java"
+ apply plugin: "java-library"
apply plugin: "eclipse"
- apply plugin: "com.ofg.uptodate"
repositories {
mavenLocal()
- jcenter()
mavenCentral()
maven {
url sonatypeRepositoryUrl
}
}
-
- tasks.withType(JavaCompile) {
- options.compilerArgs.addAll(['--release', '10'])
+ tasks.withType(JavaCompile) {
if (displayCompilerWarnings) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
+ tasks.withType(Test).configureEach {
+ maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
+ if (!generateTestReports) {
+ reports.html.required = false
+ reports.junitXml.required = false
+ }
+ }
+
+
}
task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
@@ -123,25 +136,23 @@ task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")
// We only care about coverage of:
def projectForFoverage = ["core", "quickcheck", "java-core"]
- classDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.output)
- sourceDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs)
+ getClassDirectories().from(files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.output))
+ getSourceDirectories().from(files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs))
reports {
- html.enabled = true
- xml.enabled = true
+ html.required = true
+ xml.required = true
}
}
configure(subprojects.findAll { it.name != "props-core" }) {
- apply plugin: "maven"
+ apply plugin: "maven-publish"
apply plugin: "signing"
- apply plugin: "osgi"
-
+ apply plugin: "biz.aQute.bnd.builder"
sourceCompatibility = "1.8"
javadoc {
- options.addBooleanOption('html5', true)
}
task javadocJar(type: Jar, dependsOn: "javadoc") {
@@ -161,16 +172,14 @@ configure(subprojects.findAll { it.name != "props-core" }) {
}
jar {
- version project.fjVersion
- manifest {
- name = 'Functional Java'
- instruction 'Signature-Version', project.fjVersion
- instruction 'Bundle-ActivationPolicy', 'lazy'
- instruction 'Bundle-Vendor', 'functionaljava.org'
- if(project.name != "core") {
- instruction 'Require-Bundle', 'org.functionaljava;bundle-version="'+project.fjBaseVersion+'"'
- }
- }
+ archiveVersion = project.fjVersion
+ bnd (
+ 'Bundle-Name': 'Functional Java',
+ 'Signature-Version': project.fjVersion,
+ 'Bundle-ActivationPolicy': 'lazy',
+ 'Bundle-Vendor': 'functionaljava.org',
+ 'Automatic-Module-Name': "functionaljava${project.name == 'core' ? '' : ".$project.name"}",
+ )
}
eclipse {
diff --git a/consume/build.gradle b/consume/build.gradle
index ff92a601..45dadefb 100644
--- a/consume/build.gradle
+++ b/consume/build.gradle
@@ -2,7 +2,8 @@
archivesBaseName = "${project.projectName}-${project.name}"
dependencies {
- compile("$group:$projectName:$fjConsumeVersion")
+ api "$group:$projectName:$fjConsumeVersion"
- testCompile dependencyJunit
+ testImplementation junitCompile
+ testRuntimeOnly junitRuntime
}
diff --git a/consume/src/test/java/fj/EmptyTest.java b/consume/src/test/java/fj/EmptyTest.java
index e112a97a..13675822 100644
--- a/consume/src/test/java/fj/EmptyTest.java
+++ b/consume/src/test/java/fj/EmptyTest.java
@@ -5,9 +5,6 @@
import org.junit.Assert;
-/**
- * Created by MarkPerry on 30/08/2015.
- */
public class EmptyTest {
@Ignore @Test
diff --git a/core/build.gradle b/core/build.gradle
index 13d06114..282ec191 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -1,17 +1,18 @@
ext {
signModule = true
+ uploadModule = true
+
}
archivesBaseName = project.projectName
dependencies {
- testCompile dependencyJunit
- testCompile 'com.h2database:h2:1.4.197'
- testCompile 'commons-dbutils:commons-dbutils:1.7'
+ testImplementation junitCompile
+ testRuntimeOnly junitRuntime
+ testImplementation 'com.h2database:h2:2.1.210'
+ testImplementation 'commons-dbutils:commons-dbutils:1.7'
}
performSigning(signingEnabled, signModule)
-configureUpload(signingEnabled, signModule)
-
-uploadArchives.enabled = true
+configureUpload(signingEnabled, signModule, uploadModule)
diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java
index a70629f1..5cc7f4e4 100644
--- a/core/src/main/java/fj/Bottom.java
+++ b/core/src/main/java/fj/Bottom.java
@@ -2,8 +2,6 @@
/**
* Represents the bottom _|_ value.
- *
- * @version %build.number%
*/
public final class Bottom {
private Bottom() {
diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java
new file mode 100644
index 00000000..e100b6d6
--- /dev/null
+++ b/core/src/main/java/fj/Bounded.java
@@ -0,0 +1,50 @@
+package fj;
+
+/**
+ * The Bounded class is used to name the upper and lower limits of a type.
+ * Ord is not a superclass of Bounded since types that are not totally ordered may also have upper and lower bounds.
+ */
+public final class Bounded {
+
+ private final Definition def;
+
+ /**
+ * Minimal definition of Bounded
+ */
+ public interface Definition {
+ A min();
+
+ A max();
+ }
+
+ private Bounded(Definition definition) {
+ this.def = definition;
+ }
+
+ public A min() {
+ return def.min();
+ }
+
+ public A max() {
+ return def.max();
+ }
+
+ public static Bounded boundedDef(Definition def) {
+ return new Bounded<>(def);
+ }
+
+ public static Bounded bounded(A min, A max) {
+ return boundedDef(new Definition() {
+ @Override
+ public A min() {
+ return min;
+ }
+
+ @Override
+ public A max() {
+ return max;
+ }
+ });
+ }
+
+}
diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java
index 56222de1..8bee1951 100644
--- a/core/src/main/java/fj/Class.java
+++ b/core/src/main/java/fj/Class.java
@@ -11,8 +11,6 @@
/**
* A wrapper for a {@link java.lang.Class} that provides additional methods.
- *
- * @version %build.number%
*/
public final class Class {
private final java.lang.Class c;
diff --git a/core/src/main/java/fj/Digit.java b/core/src/main/java/fj/Digit.java
index 7213e278..4fec7b0c 100644
--- a/core/src/main/java/fj/Digit.java
+++ b/core/src/main/java/fj/Digit.java
@@ -6,8 +6,6 @@
/**
* The digits zero to nine.
- *
- * @version %build.number%
*/
public enum Digit {
/**
diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java
index 80680cac..2b5dcd6f 100644
--- a/core/src/main/java/fj/Effect.java
+++ b/core/src/main/java/fj/Effect.java
@@ -14,8 +14,6 @@
/**
* Represents a side-effect.
- *
- * @version %build.number%
*/
public final class Effect {
diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java
index 5cd31aeb..cba4a589 100644
--- a/core/src/main/java/fj/Equal.java
+++ b/core/src/main/java/fj/Equal.java
@@ -22,8 +22,6 @@
/**
* Tests for equality between two objects.
- *
- * @version %build.number%
*/
public final class Equal {
@@ -357,6 +355,14 @@ public static Equal> eitherEqual(final Equal ea, final Eq
));
}
+ public static Equal> either3Equal(Equal ea, Equal eb, Equal ec) {
+ return equalDef((e1, e2) ->
+ optionEqual(ea).eq(e1.leftOption(), e2.leftOption()) &&
+ optionEqual(eb).eq(e1.middleOption(), e2.middleOption()) &&
+ optionEqual(ec).eq(e1.rightOption(), e2.rightOption())
+ );
+ }
+
public static Equal> resultEqual(final Equal ea, final Equal ei) {
Definition eaDef = ea.def;
Definition eiDef= ei.def;
diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java
index e2db316e..1736f97b 100644
--- a/core/src/main/java/fj/F.java
+++ b/core/src/main/java/fj/F.java
@@ -1,12 +1,25 @@
package fj;
+import fj.control.parallel.Actor;
+import fj.control.parallel.Promise;
+import fj.control.parallel.Strategy;
+import fj.data.*;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.TreeSet;
+import java.util.concurrent.*;
+import java.util.function.Function;
+
+import static fj.data.Option.some;
+import static fj.data.Stream.iterableStream;
+import static fj.data.Zipper.fromStream;
+
/**
- * A transformation or function from A to B. This type can be represented
- * using the Java 7 closure syntax.
- *
- * @version %build.number%
+ * A transformation or function from A to B.
*/
-public interface F {
+@FunctionalInterface
+public interface F extends Function {
/**
* Transform A to B.
*
@@ -15,4 +28,668 @@ public interface F {
*/
B f(A a);
+ default B apply(A a) {
+ return f(a);
+ }
+
+ /**
+ * Function composition
+ *
+ * @param g A function to compose with this one.
+ * @return The composed function such that this function is applied last.
+ */
+ default F o(final F g) {
+ return c -> f(g.f(c));
+ }
+
+ /**
+ * First-class function composition
+ *
+ * @return A function that composes this function with another.
+ */
+ default F, F> o() {
+ return g -> o(g);
+ }
+
+ /**
+ * Function composition flipped.
+ *
+ * @param g A function with which to compose this one.
+ * @return The composed function such that this function is applied first.
+ */
+ @SuppressWarnings("unchecked")
+ default F andThen(final F g) {
+ return g.o(this);
+ }
+
+ /**
+ * First-class composition flipped.
+ *
+ * @return A function that invokes this function and then a given function on the result.
+ */
+ default F, F> andThen() {
+ return g -> andThen(g);
+ }
+
+ /**
+ * Binds a given function across this function (Reader Monad).
+ *
+ * @param g A function that takes the return value of this function as an argument, yielding a new function.
+ * @return A function that invokes this function on its argument and then the given function on the result.
+ */
+ default F bind(final F> g) {
+ return a -> g.f(f(a)).f(a);
+ }
+
+ /**
+ * First-class function binding.
+ *
+ * @return A function that binds another function across this function.
+ */
+ default F>, F> bind() {
+ return g -> bind(g);
+ }
+
+ /**
+ * Function application in an environment (Applicative Functor).
+ *
+ * @param g A function with the same argument type as this function, yielding a function that takes the return
+ * value of this function.
+ * @return A new function that invokes the given function on its argument, yielding a new function that is then
+ * applied to the result of applying this function to the argument.
+ */
+ default F apply(final F> g) {
+ return a -> g.f(a).f(f(a));
+ }
+
+ /**
+ * First-class function application in an environment.
+ *
+ * @return A function that applies a given function within the environment of this function.
+ */
+ default F>, F> apply() {
+ return g -> apply(g);
+ }
+
+ /**
+ * Applies this function over the arguments of another function.
+ *
+ * @param g The function over whose arguments to apply this function.
+ * @return A new function that invokes this function on its arguments before invoking the given function.
+ */
+ default F> on(final F> g) {
+ return a1 -> a2 -> g.f(f(a1)).f(f(a2));
+ }
+
+
+
+ /**
+ * Applies this function over the arguments of another function.
+ *
+ * @return A function that applies this function over the arguments of another function.
+ */
+ default F>, F>> on() {
+ return g -> on(g);
+ }
+
+ /**
+ * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1.
+ *
+ * @return This function promoted to return its result in a product-1.
+ */
+ default F> lazy() {
+ return a -> P.lazy(() -> f(a));
+ }
+
+ /**
+ * Partial application.
+ *
+ * @param a The A to which to apply this function.
+ * @return The function partially applied to the given argument to return a lazy value.
+ */
+ default P1 partial(final A a) {
+ return P.lazy(() -> f(a));
+ }
+
+ /**
+ * Promotes this function to map over a product-1.
+ *
+ * @return This function promoted to map over a product-1.
+ */
+ default F, P1> mapP1() {
+ return p -> p.map(this);
+ }
+
+ /**
+ * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option.
+ *
+ * @return This function promoted to return its result in an Option.
+ */
+ default F> optionK() {
+ return a -> some(f(a));
+ }
+
+ /**
+ * Promotes this function to map over an optional value.
+ *
+ * @return This function promoted to map over an optional value.
+ */
+ default F