Created
July 6, 2018 15:08
-
-
Save mpilquist/ce80b9d381c70bc4b8c8f1262fe96800 to your computer and use it in GitHub Desktop.
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
// 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