is easier than in Go!
new LambdaWorld<Cadiz>(2018L)
https://gracious-hypatia-aac58b.netlify.com/
(Alt-P for presenter notes)
twitter: @jb9i / github: @jbgi
Typed Functional Programming is the most pratical way to write maintainable, working software.
Desired | Encoded with |
---|---|
[X] IO effect tracking | No side effects + IO<A> (from FunctionalJava). |
[X] Parametricity | Ignoring everything that can break it. |
[X] sum types / GADT | List<A>{ <X> X cases(X nil, F2<A, List<A>, X> cons);} (Scott encoding). |
[X] Expression Problem solution | Object algebras |
[X] Lazy evaluation | static <A> List<A> lazy(F0<List<A>> as) (with memoization). |
[/] HKT | List<A> => Hk<List<?>, A> (Unsafe). |
hence, in pure code, we completly ignore the existence of:
null
instanceOf
/ type castsjava.lang.Object
Same cardinality ≃ Isormorphic
Type | Cardinality |
---|---|
Void | 0 |
Unit / () | 1 |
Boolean | 2 |
Either<A, B> | A + B |
P2<A, B> | A * B |
F<A, B> | BA |
We don't know the cardinality of A!
If f
is a Functor, then:
(∀ x. (a -> x) -> f x)
≃ f a
Equivalences | Step |
---|---|
∀ x. x -> x | Introduce unit, x ≃ () -> x : |
∀ x. (() -> x) -> x | Introduce Id functor (Id x = x ): |
∀ x. (() -> x) -> Id x | Apply Yoneda: |
Id () | Id x = x : |
() | Q.E.D. |
x^a * x^b = x^(a+b)
Object are record of functions, right.
Adding a new case to Either cases
An annotation processor, compatible with most FP libs
Easy with ADT.
How to do that while reusing existing interpreter without modification?
First compile unit
First compile unit
Programs are a "monolitic" fold.
Manipulating each part as first-class values (initial algebra) simplify some tasks, eg. serialization / delegation to GPU. or just for the simpler API!
Hopefully there is an isomorphism between the two encoding (Lambek’s theorem).
data ExpF = Lit Int | Add Int Int
data Exp = Lit Int | Add Exp Exp
aka. call-by-name with sharing.
Allows to implement many operation in the cleanest FP way.
(operation that benefits from TCO (eg. foldLeft) still need while loops).
Using annotation to define field names
Scott encoding of an infinite stream
Thread-safe, tampolined lazy thunk
No HKT => cannot parametrize carrier type. Solutions:
For unsafe encoding: see the Derive4J/HKT project (provide partial safety) and application in Streams à la carte: Extensible Pipelines with Object Algebras
TypeEq: a witness of type equality.
interface Service { <R> IO<R> execute(Command<R> cmd); }
TypeEq avoid the use of continuations
and remember:
"Generics should be the tool of choice for abstracting over types."
Brian Goetz
(and "<? super/extends >" makes you lose that game)
this GADT-based service:
interface Speaker { <Answer> Option<Answer> ask(Question<Answer> q); }