Created
November 17, 2012 22:31
-
-
Save arschles/4100811 to your computer and use it in GitHub Desktop.
some of NewType
This file contains 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 characters
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])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
output is now