Scala Maybe
I wrote a Maybe (a lazy Option[T]
) that I can use in Scala.
Scala Maybe
… because I wanted a lazy
variant of Option[+T]
.
I had a use case in mind at the time, but, since then; I’ve taken another approach.
Since writing this, I’ve found an explanation of Monads that “groks” with me and multiple other places where “lazy is better” and I preffer (my) Maybe[T]
over Option[T]
.
package peterlavalle
/**
* like Option[+A] but lazy
*/
trait Maybe[+T] {
/**
* however we're implemented; ensure that any operations leading up to now are only called "once"
*/
def cache: Maybe[T]
/**
* Apply some operation to the value, and, return a new monad.
*
* this is (more likely) lazy
**/
def call[V](operation: T => V): Maybe[V]
/**
* bind it like a monad ... but ... not lazy
*/
def bind[V](operation: T => Maybe[V]): Maybe[V]
/**
* if we're empty; produce the other one
*/
def otherwise[E >: T](them: => Maybe[E]): Maybe[E]
/**
* produce/convert this to an eager Option[T] in preparation for reading or matching it.
*
* This is (kind of) a hack
*/
def some: Option[T]
final def |[V](that: T => Maybe[V]): Maybe[V] = bind(that)
final def ![V](that: T => V): Maybe[V] = call(that)
final def ?[E >: T](them: => Maybe[E]): Maybe[E] = otherwise(them)
}
object Maybe {
def apply[T](read: => T): Maybe[T] =
new Maybe[T] {
override lazy final val cache: Maybe[T] = {
lazy val data: T = read
apply(data)
}
override lazy final val some: Option[T] = Some(read)
override final def otherwise[E >: T](them: => Maybe[E]): Maybe[E] = this
override final def bind[V](map: T => Maybe[V]): Maybe[V] =
map(read)
override final def call[V](map: T => V): Maybe[V] =
Maybe {
map(read)
}
}
def unapply[T](arg: Maybe[T]): Option[T] = arg.some
case object Nope extends Maybe[Nothing] {
override final val cache: Maybe[Nothing] = this
override final val some: Option[Nothing] = None
override final def bind[V](map: Nothing => Maybe[V]): Maybe[V] = Nope
override final def call[V](map: Nothing => V): Maybe[V] = Nope
override final def otherwise[E >: Nothing](them: => Maybe[E]): Maybe[E] = them
}
}