Skip to content

Instantly share code, notes, and snippets.

@arschles
Created November 17, 2012 22:31
Show Gist options
  • Save arschles/4100811 to your computer and use it in GitHub Desktop.
Save arschles/4100811 to your computer and use it in GitHub Desktop.
some of NewType
object TaggedTypes {
sealed trait TaggedType[T] {
def underlying: T
override def toString = underlying.toString
}
//implicitly extract the primitive value from a TaggedType[T]
implicit def underlying[T](w: TaggedType[T]): T = {
w.underlying
}
//an optional TaggedType. used on construction of a NewType
type MbTaggedType[T] = Option[TaggedType[T]]
//extension methods on MbTaggedType
sealed trait MbTaggedTypeW[T] {
protected def opt: MbTaggedType[T]
def underlying: Option[T] = opt.map(_.underlying)
}
implicit def optWrapperToW[T](o: MbTaggedType[T]) = new MbTaggedTypeW[T] {
override lazy val opt = o
}
//convert a MbTaggedType[T] to an Option[T]
implicit def mbTaggedTypeOpt[T](mbTaggedType: MbTaggedType[T]): Option[T] = mbTaggedType.map(_.underlying)
private def wrapper[T](t: T): TaggedType[T] = new TaggedType[T] {
override lazy val underlying = t
}
//the constructor for new type that's based on a primitive, plus some constraints on that primitive
type TaggedTypeConstructor[T] = T => MbTaggedType[T]
//create a function that creates a MbTaggedType[T] based on the given isValid method
def NewType[T](isValid: T => Boolean): T => MbTaggedType[T] = { value: T =>
if(isValid(value)) {
Some(wrapper(value))
} else {
None
}
}
//create a function that creates a TaggedType[T] or throws based on the given isValid method.
//I don't like throwing. This method is here for practicality
def NewTypeOrThrow[T](isValid: T => Boolean): T => TaggedType[T] = { value: T =>
if(isValid(value)) { wrapper(value) } else { throw new Exception("invalid value %s".format(value.toString)) }
}
}
//a type that holds a positive integer only
import TaggedTypes._
type AppId = TaggedType[Int]
val AppId: TaggedTypeConstructor[Int] = NewType { i: Int => i > 0 }
val mbAppId1: Option[AppId] = AppId(0)
val mbAppId2: Option[AppId] = AppId(2)
val mbAppId3: Option[AppId] = AppId(-1)
println("appId1 = %s".format(mbAppId1.underlying))
println("appId2 = %s".format(mbAppId2.toString))
println("appId3 = %s".format(mbAppId3: Option[Int]))
@arschles
Copy link
Author

output is

appId1 = None
appId2 = Some(2)

@arschles
Copy link
Author

output is now

appId1 = None
appId2 = Some(2)
appId3 = None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment