Last active
November 10, 2023 18:35
-
-
Save johnhungerford/b3ccf0f46783db765688dba19bfba4a3 to your computer and use it in GitHub Desktop.
Revisions
-
johnhungerford revised this gist
Nov 9, 2023 . 1 changed file with 5 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,7 +22,7 @@ object Opt: def isDefined: Boolean = !isEmpty def nonEmpty: Boolean = isDefined def fold[U](default: => U)(f: T => U): U = if nullable == null then default else f(nullable.asInstanceOf[T]) @@ -35,17 +35,17 @@ object Opt: def toStringTagged: String = fold("None")(v => s"Some($v)") def map[U](f: T => U): Opt[U] = flatMap(f) def flatMap[U](f: T => Opt[U]): Opt[U] = if nullable == null then null else f(nullable.asInstanceOf[T]) def zip[U](other: => Opt[U]): Opt[(T, U)] = flatMap(t => other.flatMap(u => t -> u)) def getOrElse[U >: T](u: => U): U = if nullable == null then u else nullable.asInstanceOf[T] def get : T = nullable.getOrElse(throw new NullPointerException()) -
johnhungerford revised this gist
Nov 9, 2023 . 1 changed file with 0 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,10 +14,6 @@ object Opt: val None: Opt[Nothing] = null object Some: def apply[T](value: T): Opt[T] = value -
johnhungerford renamed this gist
Nov 9, 2023 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
johnhungerford created this gist
Nov 9, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,122 @@ //> using scala 3.3.0 import scala.util.{Try, Success, Failure} import scala.reflect.Typeable import scala.util.NotGiven import scala.annotation.implicitNotFound type Opt[T] = Opt.Opt[T] object Opt: opaque type Opt[+T] = T | Null def apply[T](value: T): Opt[T] = value val None: Opt[Nothing] = null extension (none: Opt[Nothing]) def unapply(isNone: Null): Option[Unit] = scala.Some(()) object Some: def apply[T](value: T): Opt[T] = value extension [T](nullable: Opt[T]) def isEmpty: Boolean = nullable == null def isDefined: Boolean = !isEmpty def nonEmpty: Boolean = isDefined def fold[O](default: => O)(f: T => O): O = if nullable == null then default else f(nullable.asInstanceOf[T]) def contains(t: T): Boolean = fold(false)(_ == t) def exists(f: T => Boolean): Boolean = fold(false)(f) def flatten[U](using hasInnerOpt: T =:= Opt[U]): Opt[U] = fold(None)(t => hasInnerOpt(t)) def toStringTagged: String = fold("None")(v => s"Some($v)") def map[O](f: T => O): Opt[O] = flatMap(f) def flatMap[O](f: T => Opt[O]): Opt[O] = if nullable == null then null else f(nullable.asInstanceOf[T]) def zip[U](other: => Opt[U]): Opt[(T, U)] = flatMap(t => other.flatMap(u => t -> u)) def getOrElse[O >: T](o: => O): O = if nullable == null then o else nullable.asInstanceOf[T] def get : T = nullable.getOrElse(throw new NullPointerException()) def toOption: Option[T] = fold(scala.None)(scala.Some.apply) def toRight[L](left: => L): Either[L, T] = if nullable == null then Left(left) else Right(nullable.asInstanceOf[T]) def toLeft[R](right: => R): Either[T, R] = if nullable == null then Right(right) else Left(nullable.asInstanceOf[T]) def toList: List[T] = fold(Nil)(_ :: Nil) def toSet: Set[T] = fold(Set.empty[T])(t => Set(t)) def toMap[K, V](using T =:= (K, V)): Map[K, V] = fold(Map.empty)(tup => Map(tup)) def toVector: Vector[T] = fold(Vector.empty)(t => Vector(t)) object syntax: extension[L, R](either: Either[L, R]) def toOpt: Opt[R] = either match case Left(_) => null case Right(value) => value def toOptLeft: Opt[L] = either match case Left(value) => value case Right(_) => null extension[T](_try: Try[T]) def toOpt: Opt[T] = _try match case Success(value) => value case Failure(_) => null def toOptFail: Opt[Throwable] = _try match case Success(_) => null case Failure(err) => err extension[T](option: Option[T]) def toOpt: Opt[T] = option.fold(Opt.None)(Opt.apply) object Main: def main(args: Array[String]): Unit = import Opt.syntax.* val a : Opt[String] = Opt("hi") val b : Opt[String] = Opt(null) val c : Opt[String] = Opt("what") val d : Opt[String] = Right("hello").toOpt val e : Opt[String] = Left('c').toOpt println(a.toStringTagged) println(b.toStringTagged) println(c.toStringTagged) println(d.toStringTagged) println(e.toStringTagged) val res1 = for { aVal <- a bVal <- b } yield aVal + aVal val res2 = for { aVal <- a cVal <- c } yield aVal + cVal println(res1.toStringTagged) println(res2.toStringTagged)