在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:palatable/lambda开源软件地址:https://github.com/palatable/lambda开源编程语言:Java 100.0%开源软件介绍:λFunctional patterns for Java Table of ContentsBackgroundLambda was born out of a desire to use some of the same canonical functions (e.g. Some things a user of lambda most likely values:
Generally, everything that lambda produces is lazily-evaluated (except for terminal operations like Although the library is currently (very) small, these values should always be the driving forces behind future growth. InstallationAdd the following dependency to your:
<dependency>
<groupId>com.jnape.palatable</groupId>
<artifactId>lambda</artifactId>
<version>5.4.0</version>
</dependency>
compile group: 'com.jnape.palatable', name: 'lambda', version: '5.4.0' ExamplesFirst, the obligatory Maybe<Integer> sumOfEvenIncrements =
reduceLeft((x, y) -> x + y,
filter(x -> x % 2 == 0,
map(x -> x + 1, asList(1, 2, 3, 4, 5))));
//-> Just 12 Every function in lambda is curried, so we could have also done this: Fn1<Iterable<Integer>, Maybe<Integer>> sumOfEvenIncrementsFn =
map((Integer x) -> x + 1)
.fmap(filter(x -> x % 2 == 0))
.fmap(reduceLeft((x, y) -> x + y));
Maybe<Integer> sumOfEvenIncrements = sumOfEvenIncrementsFn.apply(asList(1, 2, 3, 4, 5));
//-> Just 12 How about the positive squares below 100: Iterable<Integer> positiveSquaresBelow100 =
takeWhile(x -> x < 100, map(x -> x * x, iterate(x -> x + 1, 1)));
//-> [1, 4, 9, 16, 25, 36, 49, 64, 81] We could have also used Iterable<Integer> positiveSquaresBelow100 = unfoldr(x -> {
int square = x * x;
return square < 100 ? Maybe.just(tuple(square, x + 1)) : Maybe.nothing();
}, 1);
//-> [1, 4, 9, 16, 25, 36, 49, 64, 81] What if we want the cross product of a domain and codomain: Iterable<Tuple2<Integer, String>> crossProduct =
take(10, cartesianProduct(asList(1, 2, 3), asList("a", "b", "c")));
//-> [(1,"a"), (1,"b"), (1,"c"), (2,"a"), (2,"b"), (2,"c"), (3,"a"), (3,"b"), (3,"c")] Let's compose two functions: Fn1<Integer, Integer> add = x -> x + 1;
Fn1<Integer, Integer> subtract = x -> x -1;
Fn1<Integer, Integer> noOp = add.fmap(subtract);
// same as
Fn1<Integer, Integer> alsoNoOp = subtract.contraMap(add); And partially apply some: Fn2<Integer, Integer, Integer> add = (x, y) -> x + y;
Fn1<Integer, Integer> add1 = add.apply(1);
add1.apply(2);
//-> 3 And have fun with 3s: Iterable<Iterable<Integer>> multiplesOf3InGroupsOf3 =
take(3, inGroupsOf(3, unfoldr(x -> Maybe.just(tuple(x * 3, x + 1)), 1)));
//-> [[3, 6, 9], [12, 15, 18], [21, 24, 27]] Check out the tests or javadoc for more examples. SemigroupsSemigroups are supported via Semigroup<Integer> add = (augend, addend) -> augend + addend;
add.apply(1, 2); //-> 3
add.foldLeft(0, asList(1, 2, 3)); //-> 6 Lambda ships some default logical semigroups for lambda types and core JDK types. Common examples are:
Check out the semigroup package for more examples. MonoidsMonoids are supported via Monoid<Integer> multiply = monoid((x, y) -> x * y, 1);
multiply.reduceLeft(emptyList()); //-> 1
multiply.reduceLeft(asList(1, 2, 3)); //-> 6
multiply.foldMap(Integer::parseInt, asList("1", "2", "3")); //-> also 6 Some commonly used lambda monoid implementations include:
Additionally, instances of Check out the monoid package for more examples. FunctorsFunctors are implemented via the public final class Slot<A> implements Functor<A, Slot> {
private final A a;
public Slot(A a) {
this.a = a;
}
public A getA() {
return a;
}
@Override
public <B> Slot<B> fmap(Function<? super A, ? extends B> fn) {
return new Slot<>(fn.apply(a));
}
}
Slot<Integer> intSlot = new Slot<>(1);
Slot<String> stringSlot = intSlot.fmap(x -> "number: " + x);
stringSlot.getA(); //-> "number: 1" Examples of functors include:
Implementing BifunctorsBifunctors -- functors that support two parameters that can be covariantly mapped over -- are implemented via the public final class Pair<A, B> implements Bifunctor<A, B, Pair> {
private final A a;
private final B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
public A getA() {
return a;
}
public B getB() {
return b;
}
@Override
public <C, D> Pair<C, D> biMap(Function<? super A, ? extends C> lFn,
Function<? super B, ? extends D> rFn) {
return new Pair<>(lFn.apply(a), rFn.apply(b));
}
}
Pair<String,Integer> stringIntPair = new Pair<>("str", 1);
Pair<Integer, Boolean> intBooleanPair = stringIntPair.biMap(String::length, x -> x % 2 == 0);
intBooleanPair.getA(); //-> 3
intBooleanPair.getB(); //-> false Examples of bifunctors include:
Implementing ProfunctorsProfunctors -- functors that support one parameter that can be mapped over contravariantly, and a second parameter that can be mapped over covariantly -- are implemented via the Fn1<Integer, Integer> add2 = (x) -> x + 2;
add2.<String, String>diMap(Integer::parseInt, Object::toString).apply("1"); //-> "3" Examples of profunctors include:
Implementing ApplicativesApplicative functors -- functors that can be applied together with a 2-arity or higher function -- are implemented via the public final class Slot<A> implements Applicative<A, Slot> {
private final A a;
public Slot(A a) {
this.a = a;
}
public A getA() {
return a;
}
@Override
public <B> Slot<B> fmap(Function<? super A, ? extends B> fn) {
return pure(fn.apply(a));
}
@Override
public <B> Slot<B> pure(B b) {
return new Slot<>(b);
}
@Override
public <B> Slot<B> zip(Applicative<Function<? super A, ? extends B>, Slot> appFn) {
return pure(appFn.<Slot<Function<? super A, ? extends B>>>coerce().getA().apply(getA()));
}
}
Fn2<Integer, Integer, Integer> add = (x, y) -> x + y;
Slot<Integer> x = new Slot<>(1);
Slot<Integer> y = new Slot<>(2);
Slot<Integer> z = y.zip(x.fmap(add)); //-> Slot{a=3} Examples of applicative functors include:
In addition to implementing MonadsMonads are applicative functors that additionally support a chaining operation, class Person {
Optional<Occupation> occupation() {
return Optional.empty();
}
}
class Occupation {
}
public static void main(String[] args) {
Fn1<String, Either<String, Integer>> parseId = str -> Either.trying(() -> Integer.parseInt(str), __ -> str + " is not a valid id");
Map<Integer, Person> database = new HashMap<>();
Fn1<Integer, Either<String, Person>> lookupById = id -> Either.fromOptional(Optional.ofNullable(database.get(id)),
() -> "No person found for id " + id);
Fn1<Person, Either<String, Occupation>> getOccupation = p -> Either.fromOptional(p.occupation(), () -> "Person was unemployed");
Either<String, Occupation> occupationOrError =
parseId.apply("12") // Either<String, Integer>
.flatMap(lookupById) // Either<String, Person>
.flatMap(getOccupation); // Either<String, Occupation>
} In the previous example, if any of That's it. Monads are neither elephants nor are they burritos; they're simply types that support a) the ability to lift a value into them, and b) a chaining function Further, if a type is a monad, it is necessarily an TraversablesTraversable functors -- functors that can be "traversed from left to right" -- are implemented via the public abstract class Maybe<A> implements Traversable<A, Maybe> {
private Maybe() {
}
@Override
public abstract <B, App extends Applicative> Applicative<Maybe<B>, App> traverse(
Function<? super A, ? extends Applicative<B, App>> fn,
Function<? super Traversable<B, Maybe>, ? extends Applicative<? extends Traversable<B, Maybe>, App>> pure);
@Override
public abstract <B> Maybe<B> fmap(Function<? super A, ? extends B> fn);
private static final class Just<A> extends Maybe<A> {
private final A a;
private Just(A a) {
this.a = a;
}
@Override
public <B, App extends Applicative> Applicative<Maybe<B>, App> traverse(
Function<? super A, ? extends Applicative<B, App>> fn,
Function<? super Traversable<B, Maybe>, ? extends Applicative<? extends Traversable<B, Maybe>, App>> pure) {
return fn.apply(a).fmap(Just::new);
}
@Override
public <B> Maybe<B> fmap(Function<? super A, ? extends B> fn) {
return new Just<>(fn.apply(a));
}
}
private static final class Nothing<A> extends Maybe<A> {
@Override
@SuppressWarnings("unchecked")
public <B, App extends Applicative> Applicative<Maybe<B>, App> traverse(
Function<? super A, ? extends Applicative<B, App>> fn,
Function<? super Traversable<B, Maybe>, ? extends Applicative<? extends Traversable<B, Maybe>, App>> pure) {
return pure.apply((Maybe<B>) this).fmap(x -> (Maybe<B>) x);
}
@Override
@SuppressWarnings("unchecked")
public <B> Maybe<B> fmap(Function<? super A, ? extends B> fn) {
return (Maybe<B>) this;
}
}
}
Maybe<Integer> just1 = Maybe.just(1);
Maybe<Integer> nothing = Maybe.nothing();
Either<String, Maybe<Integer>> traversedJust = just1.traverse(x -> right(x + 1), empty -> left("empty"))
.fmap(x -> (Maybe<Integer>) x)
.coerce(); //-> Right(Just(2))
全部评论
专题导读
上一篇:maxmind/GeoIP2-java: Java API for GeoIP2 webservice client and database reader发布时间:2022-06-24下一篇:kousen/java_8_recipes: Source code for Modern Java Recipes book from O'Reill ...发布时间:2022-06-24热门推荐
热门话题
阅读排行榜
|
请发表评论