Java 8 : Monads
Generics: Have Typed Containers
List list = new ArrayList();
list.add("one");
list.add(1);
list.add(1L);
list.add(new Object());
Before After
List<String> list = new ArrayList<>();
list.add("one");
list.add("1");
list.add(“1212”);
Typed ContainerContainer
A Thing we cannot do with containers
Transform container of String to a container of Integers
Monad: {Type Constructor, Bind, Return}
Optional Stream
Type Constructor of of
Bind map map
Return get collect
Example:
Stream.of(1,2,3,4,5).map(i -> i + 2).collect(Collectors.toList())
Optional.of("Test").map(s -> s.concat(" ").concat(" One")).get()
https://en.wikipedia.org/wiki/Monad_(functional_programming)
Use Case of Optional: Utility method to get
encrypted password in base 64
public String encodePassword1(String password) throws Exception {
return Optional.ofNullable(password)
.map(String::getBytes)
.map(MessageDigest.getInstance("SHA1")::digest)
.map(Base64.getEncoder()::encodeToString)
.orElse(null);
//.orElseThrow(IllegalArgumentException::new);
}
public String encodePassword2(String password) throws Exception{
if (password == null)
return password;
return Base64.encode(MessageDigest.getInstance("SHA1").digest(password.getBytes()));
}
Exercise
• Write a method that accept String (which can be null) and return
number of characters in the String. If null throw
IllegalArgumentException.
Use Cases of Stream: Intro
There many Stream type constructors
• Directly from Stream class
Stream.of(T…t)
• From Collections
List<String> list = new ArrayList<>();
list.stream();
• Primitive Streams
• IntStream
• IntStream interator
IntStream.iterate(1, i -> i++).limit(100) [ for(int i = 0; i < 100; i++) ]
• Random IntStream
ThreadLocalRandom.current().ints()
• LongStream (similar to intstream)
• Buffered Reader
• new BufferedReader(new FileReader("input.txt")).lines();
Use Case of Optional: Find π with random
numbers
long sampleSize = 1_000_000_000L;
long count = ThreadLocalRandom.current().doubles(0,1)
.limit(sampleSize)
.map(d -> Math.pow(d, 2D))
.map(d -> d + Math.pow(ThreadLocalRandom.current().nextDouble(0D,1D), 2D))
.map(Math::sqrt)
.filter(d -> d < 1D)
.count();
System.out.printf("Original: %s Computed: %s %n", Math.PI, 4D * count / sampleSize );
.
.
. .
.
. .
..
.
.
.
.
.
.
.
. .
.
. .
..
.
.
.
.
.
.
.
. .
.
.
..
.
.
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
.
.
. . . .
. . ..
.
. ..
.
. . ..
.
. . .
. .
. .
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
.
.
https://codepen.io/andrewarchi/pen/mRMRed
....
....
....
.
....
.
... ..
..
.
....
....
....
.
....
.
... ..
..
.
Side Note: Using Parallel Stream
StopWatch stopWatch = new StopWatch();
stopWatch.start();
long sampleSize = 1_000_000_000L;
long count = ThreadLocalRandom.current().doubles(0,1)
.limit(sampleSize)
.parallel()
.map(d -> Math.pow(d, 2D))
.map(d -> d + Math.pow(ThreadLocalRandom.current().nextDouble(0D,1D), 2D))
.map(Math::sqrt)
.filter(d -> d < 1D)
.count();
stopWatch.stop();
System.out.printf("Original: %s Computed: %s , Time: %s %n",
Math.PI,
4D * count / sampleSize,
stopWatch);
Side Note: Use of Core
Original: 3.141592653589793 Computed: 3.141606068 , Time: 0:00:04.342
With Parallel Streams
Original: 3.141592653589793 Computed: 3.141551928 , Time: 0:00:38.072
With Serial Streams
Base Line Processes Usage
Exercise
• Read File with one billion numbers and find the Average
https://tinyurl.com/y8k8dfkf
Monad As A Design Pattern
Structural Pattern
• Operation Chaining
• Apply Functions Regardless of the result of any of them
https://github.com/iluwatar/java-design-patterns/tree/master/monad
Try Monad
Optional for NullPointerException, Try For RuntimeException
import java.util.function.Function;
public class Try<I> {
private I i;
private Try(I i) {
this.i = i;
}
// Type Constructor
public static <O> Try<O> of(O instance) {
return new Try<O>(instance);
}
// Bind
public <O> Try<O> attempt(Function<I, O> function) {
try {
O o = function.apply(i);
return new Try<O>(o);
} catch (Throwable t) {
return new Try<O>(null);
}
}
// Return
public I get() {
return i;
}
// Return
public I getOrElse(I defaultValue) {
return i == null ? defaultValue : i;
}
}
Exercise
• Write a monad which uses provided default value if the value is null when
chaining.
String lname = DeafultM.of(user)
.map(User::getName, “Roy”)
.map(s -> lastNameMap.get(s), “James”)
.get();
• Write a monad which uses provided default value if the value is not
provided criteria use when chaining.
String lname = DeafultM.of(user)
.map(User::getName, s -> s.length() < 1, “Roy”)
.map(s -> lastNameMap.get(s), s.contains(“R”), “James”)
.get();
Things to study more
• Monad functions: zip, map, flatmap, sequence
• Monad Design Pattern: https://github.com/iluwatar/java-design-
patterns/tree/master/monad
• Monoids: https://en.wikipedia.org/wiki/Monoid
• Use of Optional: https://www.programcreek.com/java-api-
examples/?api=java.util.Optional
• Functor and Monad Examples in Plain Java.
https://dzone.com/articles/functor-and-monad-examples-in-plain-
java

Java 8 monads

  • 1.
    Java 8 :Monads
  • 2.
    Generics: Have TypedContainers List list = new ArrayList(); list.add("one"); list.add(1); list.add(1L); list.add(new Object()); Before After List<String> list = new ArrayList<>(); list.add("one"); list.add("1"); list.add(“1212”); Typed ContainerContainer
  • 3.
    A Thing wecannot do with containers Transform container of String to a container of Integers
  • 4.
    Monad: {Type Constructor,Bind, Return} Optional Stream Type Constructor of of Bind map map Return get collect Example: Stream.of(1,2,3,4,5).map(i -> i + 2).collect(Collectors.toList()) Optional.of("Test").map(s -> s.concat(" ").concat(" One")).get() https://en.wikipedia.org/wiki/Monad_(functional_programming)
  • 5.
    Use Case ofOptional: Utility method to get encrypted password in base 64 public String encodePassword1(String password) throws Exception { return Optional.ofNullable(password) .map(String::getBytes) .map(MessageDigest.getInstance("SHA1")::digest) .map(Base64.getEncoder()::encodeToString) .orElse(null); //.orElseThrow(IllegalArgumentException::new); } public String encodePassword2(String password) throws Exception{ if (password == null) return password; return Base64.encode(MessageDigest.getInstance("SHA1").digest(password.getBytes())); }
  • 6.
    Exercise • Write amethod that accept String (which can be null) and return number of characters in the String. If null throw IllegalArgumentException.
  • 7.
    Use Cases ofStream: Intro There many Stream type constructors • Directly from Stream class Stream.of(T…t) • From Collections List<String> list = new ArrayList<>(); list.stream(); • Primitive Streams • IntStream • IntStream interator IntStream.iterate(1, i -> i++).limit(100) [ for(int i = 0; i < 100; i++) ] • Random IntStream ThreadLocalRandom.current().ints() • LongStream (similar to intstream) • Buffered Reader • new BufferedReader(new FileReader("input.txt")).lines();
  • 8.
    Use Case ofOptional: Find π with random numbers long sampleSize = 1_000_000_000L; long count = ThreadLocalRandom.current().doubles(0,1) .limit(sampleSize) .map(d -> Math.pow(d, 2D)) .map(d -> d + Math.pow(ThreadLocalRandom.current().nextDouble(0D,1D), 2D)) .map(Math::sqrt) .filter(d -> d < 1D) .count(); System.out.printf("Original: %s Computed: %s %n", Math.PI, 4D * count / sampleSize ); . . . . . . . .. . . . . . . . . . . . . .. . . . . . . . . . . . .. . . . . . . . . . .. . . . . . . . .. . . . . . . . . . . . . . . . .. . . .. . . . .. . . . . . . . . . . . . . . . .. . . . . . . . .. . . . . . . . . . . . . . . . .. . . . . . . . .. . . . . . . . . . https://codepen.io/andrewarchi/pen/mRMRed .... .... .... . .... . ... .. .. . .... .... .... . .... . ... .. .. .
  • 9.
    Side Note: UsingParallel Stream StopWatch stopWatch = new StopWatch(); stopWatch.start(); long sampleSize = 1_000_000_000L; long count = ThreadLocalRandom.current().doubles(0,1) .limit(sampleSize) .parallel() .map(d -> Math.pow(d, 2D)) .map(d -> d + Math.pow(ThreadLocalRandom.current().nextDouble(0D,1D), 2D)) .map(Math::sqrt) .filter(d -> d < 1D) .count(); stopWatch.stop(); System.out.printf("Original: %s Computed: %s , Time: %s %n", Math.PI, 4D * count / sampleSize, stopWatch);
  • 10.
    Side Note: Useof Core Original: 3.141592653589793 Computed: 3.141606068 , Time: 0:00:04.342 With Parallel Streams Original: 3.141592653589793 Computed: 3.141551928 , Time: 0:00:38.072 With Serial Streams Base Line Processes Usage
  • 11.
    Exercise • Read Filewith one billion numbers and find the Average https://tinyurl.com/y8k8dfkf
  • 12.
    Monad As ADesign Pattern Structural Pattern • Operation Chaining • Apply Functions Regardless of the result of any of them https://github.com/iluwatar/java-design-patterns/tree/master/monad
  • 13.
    Try Monad Optional forNullPointerException, Try For RuntimeException import java.util.function.Function; public class Try<I> { private I i; private Try(I i) { this.i = i; } // Type Constructor public static <O> Try<O> of(O instance) { return new Try<O>(instance); } // Bind public <O> Try<O> attempt(Function<I, O> function) { try { O o = function.apply(i); return new Try<O>(o); } catch (Throwable t) { return new Try<O>(null); } } // Return public I get() { return i; } // Return public I getOrElse(I defaultValue) { return i == null ? defaultValue : i; } }
  • 14.
    Exercise • Write amonad which uses provided default value if the value is null when chaining. String lname = DeafultM.of(user) .map(User::getName, “Roy”) .map(s -> lastNameMap.get(s), “James”) .get(); • Write a monad which uses provided default value if the value is not provided criteria use when chaining. String lname = DeafultM.of(user) .map(User::getName, s -> s.length() < 1, “Roy”) .map(s -> lastNameMap.get(s), s.contains(“R”), “James”) .get();
  • 15.
    Things to studymore • Monad functions: zip, map, flatmap, sequence • Monad Design Pattern: https://github.com/iluwatar/java-design- patterns/tree/master/monad • Monoids: https://en.wikipedia.org/wiki/Monoid • Use of Optional: https://www.programcreek.com/java-api- examples/?api=java.util.Optional • Functor and Monad Examples in Plain Java. https://dzone.com/articles/functor-and-monad-examples-in-plain- java