Skip to content

Instantly share code, notes, and snippets.

@tixxit
Created April 29, 2015 17:32
Show Gist options
  • Save tixxit/ab99b741d3f5d2668b91 to your computer and use it in GitHub Desktop.
Save tixxit/ab99b741d3f5d2668b91 to your computer and use it in GitHub Desktop.
import scala.language.higherKinds
trait SomeLike[+A] {
def value: A
}
trait OptionSig {
type Option[+_]
type Some[+A] <: Option[A] with SomeLike[A]
type None <: Option[Nothing]
}
abstract class OptionOps[Sig <: OptionSig] extends Extractors[Sig] {
def some[A](x: A): Sig#Some[A]
def none: Sig#None
def fold[A, B](opt: Sig#Option[A])(ifNone: => B, ifSome: A => B): B
}
trait Extractors[Sig <: OptionSig] { self: OptionOps[Sig] =>
object Some {
def unapply[A](s: Sig#Some[A]): scala.Option[A] =
scala.Some(s.value)
}
object None {
def unapply(n: Sig#None): Option[Unit] =
scala.Some(())
}
}
class Program[Sig <: OptionSig](implicit ops: OptionOps[Sig]) extends App {
import ops._
val opt: Sig#Option[Int] = none//some(42)
opt match {
case Some(42) => println("yay")
case None(_) => sys.error("")
case Some(_) => sys.error("")
}
}
sealed trait MyOpt[+A]
case class MySome[+A](value: A) extends MyOpt[A] with SomeLike[A]
case object MyNone extends MyOpt[Nothing]
trait MyOption extends OptionSig {
type Option[+A] = MyOpt[A]
type Some[+A] = MySome[A]
type None = MyNone.type
}
object MyOption {
implicit object ops extends OptionOps[MyOption] {
def some[A](x: A): MyOption#Some[A] = MySome(x)
val none: MyOption#None = MyNone
def fold[A, B](opt: MyOption#Option[A])(ifNone: => B, ifSome: A => B): B =
opt match {
case MyNone => ifNone
case MySome(x) => ifSome(x)
}
}
}
object Main extends Program[MyOption]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment