Skip to content

Instantly share code, notes, and snippets.

@jbgi
jbgi / Exp.java
Created October 8, 2018 18:05
Derive4J for extensible algebraic data types.
@Data
interface Exp {
interface ExpAlg<E, R> {
R Lit(int lit);
R Add(E e1, E e2);
}
<R> R accept(ExpAlg<Exp, R> alg);
@jbgi
jbgi / Option.scala
Created September 25, 2018 14:51
Zero-cost, subtyping-free conversion from product type to sum type
sealed trait Option[A]
sealed abstract case class Some[A](value: A) extends Option[A]
sealed abstract case class None[A]() extends Option[A]
sealed trait Id[A] { self: Option[A] =>
final def toOption: Option[A] = this
def value: A
}
@jbgi
jbgi / Parametricity.md
Last active June 18, 2018 12:12
Why I love parametricity

I try to write code that is "maximally polymorphic" to the extent that I am sufficiently familiar with the concepts involved and that I am confident of being able to efficiently explain my code to co-workers if needed.

I started to use generics in Java to improve reuse of the libraries I wrote at work, but as I was growing a better understanding of types, parametricity and theorems for free, other compelling reasons became prominent:

  1. the free theorems help me reason about code: given parametricity, I know what a function can do and cannot do, based only on its type signature. Eg. given an unconstrained type variable, any value of this type that appears in positive position (output)
@jbgi
jbgi / Program.java
Created October 15, 2017 06:54
Using existentials to implement abstract type alias in Java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
interface Person {
int age();
}
interface People<T> {
T fromList(List<Person> ps);
@jbgi
jbgi / Either.java
Last active May 7, 2017 21:40
Automatic derivation of FJ Equal/Hash/Show/Ord "type classes" via derive4j processor-api
import fj.Equal;
import fj.Hash;
import fj.Ord;
import fj.Show;
import java.util.function.Function;
import org.derive4j.Data;
import org.derive4j.Derive;
import org.derive4j.Instances;
@Data(@Derive(@Instances({ Show.class, Hash.class, Equal.class, Ord.class})))
@jbgi
jbgi / ClosestSolutionFound.scala
Last active April 25, 2017 14:14
How to pattern match with implicit conversion?
trait A {
def toB: B
}
object A {
def unapply(arg: A): B = arg.toB
}
sealed trait B {
def isEmpty: Boolean = false
def get: B = this
import java.io.IOException;
import org.derive4j.hkt.__;
public abstract class Label<T> {
private Label(){}
public abstract T apply(String s);
public abstract String unwrap(T lbl);
public abstract <f> __<f, String> subst(__<f, T> fa);
@jbgi
jbgi / FileSinks.scala
Last active December 16, 2016 09:16
"Atomic" file sink through temporary file sink + renaming
import java.nio.file._
import java.util.concurrent.Executor
import akka.Done
import akka.stream.IOResult
import akka.stream.scaladsl.{FileIO, Sink}
import akka.util.ByteString
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
@jbgi
jbgi / Either.scala
Last active April 21, 2017 09:29
Minimal Either sum type in Scala
sealed trait Either[A, B]
final case class Left[A, B](a: A) extends Either[A, B]
final case class Right[A, B](b: B) extends Either[A, B]
object Either {
def left[A, B](a: A): Either[A, B] = Left(a)
def right[A, B](b: B): Either[A, B] = Right(b)
}
@jbgi
jbgi / Either.java
Last active February 9, 2017 07:03
Minimal Either in Java with Derive4J
import java.util.function.Function;
import org.derive4j.Data;
@Data
interface Either<A, B> {
<X> X match(Function<A, X> left, Function<B, X> right);
static void main(String[] args) {