Skip to content

Instantly share code, notes, and snippets.

@guizmaii
Created February 26, 2025 04:46
Show Gist options
  • Save guizmaii/c18ae00eae9da58591d2c2135edc5c90 to your computer and use it in GitHub Desktop.
Save guizmaii/c18ae00eae9da58591d2c2135edc5c90 to your computer and use it in GitHub Desktop.
/**
* Scala 2 encoding for the union type `T | Null`
*
* This encoding implementation is copied from the implementation of [[scala.Option]]
*
* See tweets to see the explored encodings: https://twitter.com/guizmaii/status/1481530910290100227?s=20
*
* Why do we need this weird type? See https://twitter.com/guizmaii/status/1481543904734617601?s=20
*/
sealed abstract class Nullable[+A] extends Product with Serializable {
def toOption: Option[A]
def orNull: A
def map[B](f: A => B): Nullable[B]
}
object Nullable {
case object Empty extends Nullable[Null] {
override def toOption: Option[Null] = None
override def orNull: Null = null
override def map[B](f: Null => B): Nullable[B] = empty
}
final case class Value[+A](value: A) extends Nullable[A] {
override def toOption: Option[A] = Some(value)
override def orNull: A = value
override def map[B](f: A => B): Nullable[B] = Nullable(f(value))
}
def empty[T]: Nullable[T] = Empty.asInstanceOf[Nullable[T]]
def apply[A](a: A): Nullable[A] = if (a == null) empty else Value(a)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment