Skip to content

Instantly share code, notes, and snippets.

@noelwelsh
Created April 17, 2015 10:38
Show Gist options
  • Select an option

  • Save noelwelsh/02b9ecf6d21c7b8934e8 to your computer and use it in GitHub Desktop.

Select an option

Save noelwelsh/02b9ecf6d21c7b8934e8 to your computer and use it in GitHub Desktop.

Revisions

  1. Noel Welsh created this gist Apr 17, 2015.
    47 changes: 47 additions & 0 deletions Nullable.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    object Nullable {
    sealed trait NullableTag
    type Nullable[A] = A with NullableTag

    def nullAs[B]: Nullable[B] =
    null.asInstanceOf[Nullable[B]]

    implicit class ToNullable[A](val a: A) extends AnyVal {
    def `?`: Nullable[A] = a.asInstanceOf[Nullable[A]]
    }

    implicit class NullableOps[A](val a: Nullable[A]) extends AnyVal {
    def map[B](f: A => B): Nullable[B] =
    if(a == null) {
    nullAs[B]
    } else
    f(a).?

    def flatMap[B](f: A => Nullable[B]): Nullable[B] =
    if(a == null)
    nullAs[B]
    else
    f(a).?

    def fold[B](empty: B)(full: A => B): B =
    if(a == null)
    empty
    else
    full(a)

    def getOrElse(empty: A): A =
    if(a == null)
    empty
    else
    a
    }
    }

    object Examples {
    import Nullable._

    def notNull =
    ("hi").? map (_ ++ " there") flatMap (a => if(a.length < 2) null else "dawg".?) getOrElse "dang"

    def isNull =
    ("").? map (_ ++ "") flatMap (a => if(a.length < 2) null else "yeah".?) getOrElse "dang"
    }