Principal Officer & Developer
Norwegian JUG javaBin, Oslo Organizer
Who am I and why listen to me?
Oslo Software Architecture Co-Organizer
Java Champion
Writing as less code as possible is not a goal itself for the Java programming language.
Make it easier to build and maintain reliable code ... that's why people continue to use and trust Java.
- Brian Goezt
JEP-359 Records
JEP-360 Sealed Types
JEP-169 Value Types
JEP-305 Pattern Matching, instanceof
JEP-325 & 354 Switch Expressions
JEP-405: Record & Array Patterns
Deconstructional pattern matching like in
As other languages move towards functional style, Haskell get better tooling, libraries, stable releases, a growing community and increased industry adoption.
Haskell is constructed by expressions, not statements. Side-effects and mutation is hard, but is still possible. Haskell has tens of extensions called pragmas, that can be enabled.
Java src code
bytecode
machine code
JIT Compiler
Java Compiler
No optimization
JIT optimization
Haskell src code
Core code
machine code
STG code
HS Compiler
C - - code
C code
LLVM code
Low-level imperative language.
Optimisation
Parsing
Code-generation
Classloader
Java Class file
(Java Bytecode)
Execution
Engine
Native Method
Interface / Libraries
Heap
Stacks
Registers
Methods
STG-Program Code (machine code)
STG-machine
Executable binary file
Registers
Heap
Stacks
GHC Libraries
Haskell
Execution Context
(HEC)
Heap
Registers
*.java
JVM
*.hs
GHC
RTS
Separate pure and impure code as much as you can!
main = do
putStrLn "Write a line: "
line <- getLine
putStrLn $ "Input was: " ++ line
-- impure
main = do
putStrLn "Write a line: "
line <- getLine
putStrLn $ (append line)
-- pure
append :: String -> String
append input = "Input was: " ++ inputappend is referentially transparent.
Sequencing (imperative style)
repl.it/@dervism/JavaLazyEval
double, long, int, float, char, short, byte, boolean, String
Int, Integer, Double, Float, Bool, Bits, Char, String
Primitives:
- Int#, Double#, Float#, Word#, Char#
Signed integrals:
- Int8, Int16, Int32, Int64
Haskell optimizes your code to use primitives (when possible).
Don't use Haskell's primitive types:
Int# causes eager evaluation!
Bits: Import Data.Bits, GHC.Prim + enable MagicHash extension.
int[] ints = new ints[6];
ints = array (0, 5) [(i, 0) | i <- [0..5]]
ints[5] = 10;
ints // [(5,10)]
int val = ints[5];
val = (ints ! 5)
new ints[] {1, 2, 3};
array (0,2) [(0,1), (1,2), (2,3)]
new ints[] {1, 2, 3};
listArray (0,2) [i+1 | i <- [0..2]]
listArray ('a','h') [i | i <- [0..8]]
Map<Character, Integer>
Haskell arrays are lazy and immutable.
Haskell provides mutable arrays
Haskell arrays are extremely flexible with enums.
Import Data.Array
https://replit.com/@dervism/Arrays
This OR That.
This AND That
https://en.wikipedia.org/wiki/Tagged_union
Java Records, Haskell ADTs (one constructor), Java classes, C structs, tuples
https://en.wikipedia.org/wiki/Product_type
Java enums(*), Haskell ADTs (several data constructors)
Also called: variant, choice type, discriminated union, disjoint union, coproduct
* all values must have the same constructor
This OR That.
This AND That
Records
Sealed classes & interfaces
Exhaustive Pattern Matching
Destructuring / Decomposition
Erik Dreyer
data Animal = Dog | Cat | Elkdata Animal = Dog String
| Cat String
| Elk String
name (Dog n) = n
name (Cat n) = n
name (Elk n) = nrepl.it/@dervism/enumeration
Function<Animal, String> name = a -> a.name;
enum Animal {
DOG("Max"), CAT("Nala"), ELK("Sam");
String name;
Animal(String name) {
this.name = name
}
}enum Animal { DOG, CAT, ELK }replit.com/@dervism/JavaEnum
data Animal = Dog String
| Cat String Int
| Elk Int String Double
| Unknown
info (Dog n) = "Dog: " ++ n
info (Cat n _) = "Cat: " ++ n
info (Elk _ n _) = "Elk: " ++ n
info _ = "Unknown animal"repl.it/@dervism/enumeration
enum Group { Mammal, Bird, Fish }
record Animal(String name, int age, Group group) {}
var elephant = new Animal("Elephant", 10, Mammal);
String name = elephant.name();
int age = elephant.age();
Type group = elephant.group();github.com/dervism/java14-demo
data Group = Mammal | Bird | Fish deriving (Show)
data Animal = Animal {
name :: String,
age :: Int,
group :: Group
}
elephant = (Animal "Elephant" 10 Mammal)
elephantName = name a
elephantAge = age a
elephantGroup = group arepl.it/@dervism/enumeration
data Person = Person {
name :: String,
adress :: String
}
data Country = Country {
name :: String
}
toStr a = join "," [name a, adress a]main.hs: error:
Multiple declarations of `name'
Declared at: main.hs:2:4
main.hs:7:4{-# LANGUAGE DuplicateRecordFields #-}
data Person = Person {
name :: String, adress :: String
}
data Country = Country {
name :: String
}
toStr a = join "," [name (a::Person), adress a]replit.com/@dervism/duplicate-names
data Spec = Spec {
engineType :: Engine,
maxSpeed :: Speed,
featureList :: [Feature]
}
data Automobile =
Car Spec | Bus Spec | Bike Spec
class Transport a where
spec :: a -> Spec
instance Transport Automobile where
spec (Car s) = s
spec (Bus s) = s
spec (Bike s) = srecord Spec(
Engine engineType,
Speed maxSpeed,
List<Feature> featureList
) {}
interface Transport {
Spec spec();
}
sealed interface Automobile extends Transport
permits Car, Bus, Bike {}
final class Bus implement Automobile {
public Bus(Spec spec) {
this.spec = spec;
}
public Spec spec() {
return spec;
}
}
record Spec(
Engine engineType,
Speed maxSpeed,
List<Feature> featureList
) {}
interface Transport {
Spec spec();
}
sealed interface Automobile extends Transport
permits Car, Bus, Bike, Any {}
non-sealed class Any implement Automobile {
...
}
// non-sealed:
// support specific extension points
// while restricting others
// https://stackoverflow.com/a/63887136The Haskell compiler inlines referentially transparent functions, and "unboxes" ADTs where possible.
inline class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int x() { return x; }
public int y() { return y; }
}openjdk.java.net/jeps/169
cr.openjdk.java.net/~briangoetz/valhalla/sov/02-object-model.html
inline class Point {
int x;
int y;
}class Line {
Point x;
Point y;
}class Line {
int x1;
int y1;
int x2;
int y2;
}Toby Ajila - Valhalla experts group
Spaces and tabs are ignored.
Indentation matters.
Braces and semicolons are required.
Braces and semicolons are optional.
public class MyClass {
public int add(int x, int y){
return x + y;
}
public String hello(){
return "Hello, world!";
}
}module MyClass where
add :: Int -> Int -> Int
add x y = x + y
hello :: String
hello = "Hello, world!"module MyClass where
add x y = x + y
hello = "Hello, world!"import java.lang.*;
import java.util.Map;
import static
java.util.Arrays.sort;
public class MyClass {
...
}import Prelude
import Data.Map
import qualified Data.Map as M
import Data.List (filter, sort)
import Data.List hiding (nub)
module MyClass where
module com.testmodule {
requires module.name;
exports mypackage.name;
}module ChessGame (
Result(..)
easy,
difficult,
run) where
run level = play level
easy = (Chess Normal)
difficult = (Chess Strong)
data Result = Won | Lost | Draw
-----------------------------------
data Ai = Normal | Strong
data Chess = Chess Ai
class Game a where
play :: a -> Result
instance Game Chess where
play chessAi = ....
Visibility and encapsulation via: private, public, protected, default, static
public interface Person<A> {
String name(A a);
}class Person a where
name :: a -> Stringclass Person a where
name :: a -> String
data Teacher = Teacher { tName :: String, tAge :: Int }
data Student = Student { sName :: String, sAge :: Int }
instance Person Teacher where
name teacher = tName teacher
age teacher = tAge teacher
instance Person Student where
name student = sName student
age student = sAge student
personAge :: Person p => p -> Int
personAge p = age p
main = do
let
teacher = (Teacher "Jane" 30)
student = (Student "Peter" 30)
teacherName = name teacher
studentName = name student
putStrLn $ "Age of " ++ teacherName ++ " " ++ (show $ personAge teacher)
putStrLn $ "Age of " ++ studentName ++ " " ++ (show $ personAge teacher)
repl.it/@dervism/typeclasses
repl.it/@dervism/JavaTypeclasses
interface Person {
String name();
}
class Student implements Person {
String sName; int sAge;
public Student(String sName, int sAge) {
this.sName = sName;
this.sAge = sAge;
}
@Override
public String name() {
return "Hello to " + this.sName;
}
}
class Teacher implements Person {
String tName; int tAge;
public Teacher(String tName, int tAge) {
this.tName = tName;
this.tAge = tAge;
}
@Override
public String name() {
return "Hello to " + this.sName;
}
}
class Main {
public static void main(String[] args) {
Teacher t = new Teacher("Jane", 30);
System.out.println(t.name());
Student s = new Student("Peter", 30);
System.out.println(s.name());
}
}data Person = Person {
salary :: Int,
taxClass :: TaxClass
}if (salary > 900)
tax = salary * 0.44;
else
tax = salary * 0.36;if salary > 900
then salary * 0.44
else salary * 0.36if (salary > 900)
return salary * 0.44;
else if (salary > 500)
return salary * 0.36;
else
return salary * 0.24;if salary > 900
then salary * 0.44
else if salary > 500
then salary * 0.36
else salary * 0.24if salary > 900
then salary * 0.44
else if salary > 500
then salary * 0.36
else salary * 0.24tax salary
| salary > 900 = salary * 0.44
| salary > 500 = salary * 0.36
| otherwise = salary * 0.24tax salary
| salary > 900 = salary * 0.44
| salary > 500 = salary * 0.36
| otherwise = salary * 0.24tax salary = salary * taxClass
where taxClass
| salary > 900 = 0.44
| salary > 500 = 0.36
| otherwise = 0.24switch (taxClass) {
case CLASS_1:
return 0.44;
case CLASS_2:
return 0.36;
}case taxClass of
CLASS_1 -> 0.44
CLASS_2 -> 0.36switch (taxClass) {
case CLASS_1:
tax = 0.44;
break;
case CLASS_2:
tax = 0.36;
break;
}switch (taxClass) {
case CLASS_1 -> 0.44;
case CLASS_2 -> 0.36;
}case taxClass of
CLASS_1 -> 0.44
CLASS_2 -> 0.36float clz = switch (taxClass) {
case CLASS_1 -> 0.44;
case CLASS_2 -> 0.36;
}float value = switch (taxClass) {
case CLASS_1 -> {
System.out.println("High tax level.");
yield 0.44;
}
case CLASS_2 -> {
System.out.println("Regular tax level.");
yield 0.36;
}
default -> {
System.out.println("Low tax level.");
yield 0.24;
}
};enum Letter {A, B, C, D};
public String getLetter(Letter letter) {
return switch (letter) {
case A, B, C, D -> "A letter";
default -> "Unknown";
};
}
data Letter = A | B | C | D deriving (Enum, Eq)
letter :: Letter -> String
letter letter
| elem letter [A .. D] = "A letter"
| otherwise = "Unknown"repl.it/@dervism/control-structures
Algol60
Fortran
Lisp
1958-60
Cobol
Algol60
Fortran
Lisp
Simula
1962
1958-60
Cobol
Algol60
Fortran
Lisp
Simula
Simula67
1967
1962
1958-60
Cobol
Algol60
Fortran
Lisp
Simula
Simula67
SmallTalk
C
1972
1967
1962
1958-60
Cobol
Pascal
Algol60
Fortran
Lisp
Simula
Simula67
SmallTalk
C
1980-86
Objective-C
C++
Eiffel
Ada
1972
1967
1962
1958-60
Cobol
Pascal
Algol60
Fortran
Lisp
Simula
Simula67
SmallTalk
C
1980-86
Objective-C
C++
Eiffel
Ada
1972
1967
1962
1958-60
Python
Java
1990-95
Cobol
Pascal
Ruby
JavaScript
Algol60
Fortran
Lisp
Simula
Simula67
SmallTalk
C
1980-86
Objective-C
C++
Eiffel
Ada
1972
1967
1962
1958-60
Python
Java
1990-95
Cobol
Pascal
Ruby
JavaScript
2009+
Rust
Swift
Go
Scala
Kotlin
2004
Algol60
Fortran
Lisp
Simula
Simula67
SmallTalk
C
1980-86
Objective-C
C++
Eiffel
Ada
1972
1967
1962
1958-60
Python
Java
1990-95
Cobol
Pascal
Ruby
JavaScript
2009+
Rust
Swift
Go
Scala
Kotlin
2004
Procedural
Object-Oriented
Multi-Paradigm
Algol60
Fortran
Lisp
Simula
Simula67
SmallTalk
C
1980-86
Objective-C
C++
Eiffel
Ada
1972
1967
1962
1958-60
Python
Java
1990-95
Cobol
Pascal
Ruby
JavaScript
2009+
Rust
Swift
Go
Scala
Kotlin
2004
Procedural
Object-Oriented
202x+
Multi-Paradigm
Functional?
@dervismn
dervis.no
Thanks!
https://github.com/dervism
https://repl.it/@dervism
Avoid null values
Do not throw exceptions
Preform side-effects in a safe manner
Easily change fields with immutable structures
@dervismn
dervis.no
Thanks!
https://github.com/dervism
https://repl.it/@dervism
Search for packages.
Search for functions and types.
https://hoogle.haskell.org/
https://hackage.haskell.org/
record Person(name, age) {}
Person = name AND age
sealed interface Person
permits Teacher, Student
switch (person) {
case Teacher(name, age) -> ...
case Student(name, _) -> ...
}
module com.testmodule {
requires module.name;
requires static module.name;
requires transitive module.name;
exports package.name;
export package.name
to some.package;
opens com.package;
opens com.package
to another.module;
}https://bit.ly/devoxxpl21dm