Skip to content

Instantly share code, notes, and snippets.

@simerplaha
Created November 22, 2019 01:26
Show Gist options
  • Save simerplaha/349f5c522733834ab1abbb8b45831cfb to your computer and use it in GitHub Desktop.
Save simerplaha/349f5c522733834ab1abbb8b45831cfb to your computer and use it in GitHub Desktop.
//See - https://gist.github.com/milessabin/89c9b47a91017973a35f && https://github.com/softwaremill/scala-common
object Tagged {
sealed trait Tagged[+T] extends Any {
type Tagged <: T
}
type @@[+V, +T] = V with Tagged[T]
}
sealed trait MaybeTag
object Maybe {
import Tagged.@@
type Maybe[A] = @@[A, MaybeTag]
def none[A]: Maybe[A] =
null.asInstanceOf[Maybe[A]]
def some[A](value: A): Maybe[A] =
value.asInstanceOf[@@[A, MaybeTag]]
implicit class ArrayImplicits[A](array: Array[A]) {
final def findMaybe(p: A => Boolean): Maybe[A] = {
var i = 0
while (i < array.length - 1) {
val item = array(i)
if (p(item))
return Maybe.some(item)
else
i += 1
}
Maybe.none[A]
}
}
implicit class MaybeImplicits[A](value: Maybe[A]) {
def isNone: Boolean =
value == null
def isSome: Boolean =
value != null
def mapMayBe[B](f: A => B): Maybe[B] =
map(f)
def map[B](f: A => B): Maybe[B] =
if (value == null)
none[B]
else
some(f(value))
def flatMapMayBe[B](f: A => Maybe[B]): Maybe[B] =
flatMap(f)
def flatMap[B](f: A => Maybe[B]): Maybe[B] =
if (value == null)
none[B]
else
f(value)
def foreachMayBe(f: A => Unit): Unit =
foreach(f)
def foreach(f: A => Unit): Unit =
if (value != null)
f(value)
def getUnsafe: A =
if (value == null)
throw new NoSuchElementException("MayBe.getUnsafe")
else
value
def orElseMayBe[B >: A](other: => Maybe[B]): Maybe[B] =
orElse[B](other)
def orElse[B >: A](other: => Maybe[B]): Maybe[B] =
if (value == null)
other
else
value.asInstanceOf[Maybe[B]]
def applyOrElse[T](onSome: A => T, onNone: => T): T =
if (value == null)
onNone
else
onSome(value)
def getOrElseMayBe[B >: A](other: => B): B =
getOrElse[B](other)
def getOrElse[B >: A](other: => B): B =
if (value == null)
other
else
value
def foldLeftMayBe[B](initial: B)(f: (A, B) => B): B =
foldLeft[B](initial)(f)
def foldLeft[B](initial: B)(f: (A, B) => B): B =
if (value == null)
initial
else
f(value, initial)
def toOption: Option[A] =
Option(value)
}
}
object Tester extends App {
import Maybe._
val one: Maybe[Int] = Maybe.some(1)
val two: Maybe[Int] =
one.flatMap {
integer =>
Maybe.some(integer + 1)
}
assert(two == 2)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment