Skip to content

Instantly share code, notes, and snippets.

@igstan
Last active July 21, 2020 19:23
Show Gist options
  • Save igstan/88d44b0d97e7b8e8bf1f0bbdc3c49cff to your computer and use it in GitHub Desktop.
Save igstan/88d44b0d97e7b8e8bf1f0bbdc3c49cff to your computer and use it in GitHub Desktop.
trait Optional[A] {
def visit[R](visitor: Optional.Visitor[A, R]): R
// Alias to show that visiting is similar to pattern matching.
def matching[R](visitor: Optional.Visitor[A, R]): R =
visit(visitor)
}
object Optional {
// Lists all the cases that must be handled when visiting.
//
// In the standard Visitor pattern, these two methods would have been
// called `visit(a: Some)` and `visit(a: None)`. I find the version
// below way nicer.
trait Visitor[A, R] {
def none: R
def some(value: A): R
}
/** Factory method for None values. */
def none[A]: Optional[A] =
new Optional[A] {
override def visit[R](visitor: Optional.Visitor[A, R]) =
visitor.none
}
/** Factory method for Some values. */
def some[A](value: A): Optional[A] =
new Optional[A] {
override def visit[R](visitor: Optional.Visitor[A, R]) =
visitor.some(value)
}
}
object Example {
def main(args: Array[String]): Unit = {
val optional: Optional[Int] = Optional.some(1)
val result =
optional.matching(new Optional.Visitor[Int, String] {
override def none =
"none"
override def some(value: Int) =
s"some($value)"
})
println(s"result: $result")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment