Skip to content

Instantly share code, notes, and snippets.

@mpilquist
Created July 6, 2018 15:08
Show Gist options
  • Save mpilquist/ce80b9d381c70bc4b8c8f1262fe96800 to your computer and use it in GitHub Desktop.
Save mpilquist/ce80b9d381c70bc4b8c8f1262fe96800 to your computer and use it in GitHub Desktop.
// Range is a product of two ints that implicitly carries a proof that start <= end.
// We can model this in scala as a case class with a validating apply method.
// Note: requires relatively recent 2.12 release
final case class Range private (start: Int, end: Int) {
def copy(start: Int = this.start, end: Int = this.end): Option[Range] = Range(start, end)
}
object Range {
def apply(start: Int, end: Int): Option[Range] =
if (start <= end) Some(new Range(start, end)) else None
}
// We lose the ability to get a Generic[Range] due to the private constructor, which is good!
// However, it's still useful to do metaprogramming with such datatypes, perhaps via something like:
trait PartialGeneric[A] {
type Repr
def to(a: A): Repr
def from(r: Repr): Option[A]
}
// This would let us derive things like codecs.
// One thing that is kind of interesting is representing Range as a straight sum of products type with an additional component in the product that represents a proof of the condition enforced in the Repr => Option[A] function.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment