The emergence of support of functions and lambda expressions as first-class citizens in Java 8 gives us a tremendous opportunity to adapt the concepts of functional programming to the Java language.
2. IntroIntro
All Java code can be found at Javaz
https://github.com/escalate42/Javaz
The emergence of native support for lambdas in Java 8
has opened the possibility to adapt the rich experience
of statically typed functional programming languages to
the Java world. So the Javaz appears.
finally!This presentation can be found at
https://slides.com/vadimdubs/javaz
4. TypeclassesTypeclasses
First appeared in Haskell programing langugage
Is a sort of interface that defines some behavior
You can think of them kind of as Java interfaces
5.
6. -- Typeclass definition with name Eq, type variable a
-- and function == which has two params of type a and
-- returns Bool
class Eq a where
eq :: a -> a -> Bool
-- Data Type definition (like Java enum in this case)
data TrafficLight = Red | Yellow | Green
-- Instance definition for TrafficLight data type and
-- Eq typeclass
instance Eq TrafficLight where
eq Red Red = True
eq Yellow Yellow = True
eq Green Green = True
eq _ _ = False
7. public interface Eq<A> {
public boolean eq(A other);
}
public final class TrafficLight implements Eq<TrafficLight> {
public static TrafficLight RED = new TrafficLight();
public static TrafficLight YELLOW = new TrafficLight();
public static TrafficLight GREEN = new TrafficLight();
private TrafficLight() {}
@Override
public boolean eq(TrafficLight other) {
return other == this;
}
}
38. f :: a -> M a
g :: a -> M b
-- Bind function
(>>=) :: M a -> (a -> M b) -> M b
a -> (f a) >>= a -> (g a)
-- Same in term of types
-- (>>=) is the same as
-- composition of functions
(a -> M a) >>= (a -> M b)
-- Composition of functions
(a -> a) . (a -> b)
41. OptionOption
For optional values, typesafe way to avoid null and null-checks
Option<T> always is in one of two states:
Some<T> - simple container for value of type T
None<T> - represents absence of any value of type T
Javaz implementation
42. User auth(String l, String p);
Role getRole(User u);
Permissions getPermissions(Role r);
List<Partner> getPartners(Permissions p);
User user = auth("user", "password");
Role role = null;
Permissions permissions = null;
List<Partner> partners = new ArrayList<>();
if (user != null) {
role = getRole(user);
}
if (role != null) {
permissions = getPermissions(role);
}
if (permissions != null) {
partners.addAll(getPartners(permissions));
}
43. Function2<String, String, Option<User>> auth;
Function<User, Option<Role>> getRole;
Function<Role, Option<Permissions>> getPermissions;
Function<Permissions, List<Partner>> getPartners;
List<Partner> partners =
// trying to authenticate user
auth.apply("login", "password")
// trying to get Role for this
// user from service via http
.flatMap(getRole) // the same as >>=
// trying to load permissions
// from database
.flatMap(getPermissions)
// trying to load partners from
// another data source
.map(getPartners) // the same as fmap
.getOrElse(new ArrayList());
44. OptionalOptional
import static Optional.of;
import static Optional.empty;
final Optional<Integer> first = of(3);
final Optional<Integer> second = of(4);
final Optional<Integer> empty = empty();
// Optional is a functor and monad
first.map(i -> i * i) // Some(9)
empty.map(i -> i * i) // None
first.flatMap(f -> second.map(s -> f + s));
// Some(7)
first.flatMap(f -> empty.map(s -> f + s));
// None
Implementation from standard Java 8 library
45. EitherEither
For results that either success or failure, typesafe way to avoid
usege of exceptions.
Has no analogs in standard Java library.
Either<L, R> always is in one of two states:
Right<L, R> - container for value of type R
Left<L, R> - container for values of type L that represents some
failure
Javaz implementation
46. F2<String, String, Either<ErrorInfo, User>> auth;
F<User, Either<ErrorInfo, Role>> getRole;
F<Role, Either<ErrorInfo, Permissions>> getPermissions;
F<Permissions, List<Partner>> getPartners;
Either<ErrorInfo, List<Partner>> eitherPartners =
// trying to authenticate user
auth.apply("login", "password")
// trying to get Role for this
// user from service via http
.fmap(getRole)
// trying to load permissions
// from database
.fmap(getPermissions)
// trying to load partners from
// another data source
.map(getPartners);
eitherPartners.mapLeft(logger::error);
List<String> partnerNames = eitherPartners.foldRight(
new ArrayList(), partner -> partner.getName
)
47. StreamStream
final Stream<Integer> stream =
Arrays.asList(1, 2, 3, 4, 5).stream();
// Streams are functors
stream.map(i -> i + 1);
// [2, 3, 4, 5, 6]
stream.forEach(System.out::print);
// out > 12345
Implementation from standard Java 8 library
48. StreamStream
final Stream<Integer> stream
= Arrays.asList(1, 2, 3, 4, 5).stream();
// Streams are monads
stream.flatMap(
i -> Arrays.asList(i + 1, i + 2).stream()
);
// [2, 3, 3, 4, 4, 5, 5, 6, 6, 7]
Implementation from standard Java 8 library
49. StreamStream
Function<User, Stream<Permission>> permissionsByUser;
Function<Permission, Stream<Partner>> partnersByPermissions;
Stream<User> users = Arrays.asList(user1, user2).stream();
Set<Partners> availablePartners = users
.flatMap(permissionByUser)
// get all permissions of user 1 and user2
.distinct()
// left only unique items
.flatMap(partnersByPermissions)
// get all partners available through permissions
.collect(Collectors.toSet);
Implementation from standard Java 8 library