Last active
December 20, 2015 22:38
-
-
Save tpolecat/6205985 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
package time.calendar | |
import scalaz.Enum | |
import scalaz.Ordering | |
import shapeless._ | |
import shapeless.Nat._ | |
import shapeless._ | |
import shapeless.Nat._ | |
import shapeless.LTEq._ | |
/** Proof that A <= B <= C ... is this worth the effort? */ | |
trait Incl[A <: Nat, B <: Nat, C <: Nat] | |
object Incl { | |
implicit def MkIncl[A <: Nat, B <: Nat, C <: Nat](implicit a: A <= B, b: B <= C): Incl[A, B, C] = | |
new Incl[A, B, C] {} | |
} | |
/** Enumerated type; there are exactly 7, with ordinals 1 .. 7 */ | |
sealed trait Weekday { | |
type Ord <: Nat // type-level ordinal | |
def ord: Int // value-level ordinal | |
} | |
// Intermediate class makes construction easier and safer, without exposing the type param | |
// in the outer type. Is this worth the effort? | |
sealed abstract class MkWeekday[N <: Nat: ToInt] extends Weekday { | |
type Ord = N | |
val ord = toInt[Ord] | |
} | |
case object Sun extends MkWeekday[_1] | |
case object Mon extends MkWeekday[_2] | |
case object Tue extends MkWeekday[_3] | |
case object Wed extends MkWeekday[_4] | |
case object Thu extends MkWeekday[_5] | |
case object Fri extends MkWeekday[_6] | |
case object Sat extends MkWeekday[_7] | |
object Weekday extends WeekdayFunctions with WeekdayInstances { | |
def fromOrdinal(n: Int): Option[Weekday] = | |
values.find(_.ord == n) | |
def fromNat[N <: Nat: ToInt](implicit ev: Incl[_1, N, _7]): Weekday = | |
fromOrdinal(toInt[N]).get // ** unsafe, can we improve this? | |
} | |
trait WeekdayFunctions { | |
val values: List[Weekday] = | |
List(Sun, Mon, Tue, Wed, Thu, Fri, Sat) // unsafe, can we improve this? | |
} | |
trait WeekdayInstances { this: Weekday.type => | |
// Also need to fix this up; ignore for now | |
implicit def enum = new Enum[Weekday] { | |
def succ(a: Weekday): Weekday = fromOrdinal((a.ord % 7) + 1).get | |
def pred(a: Weekday): Weekday = fromOrdinal(((a.ord + 5) % 7) + 1).get | |
def order(x: Weekday, y: Weekday): Ordering = Ordering.fromInt(x.ord - y.ord) | |
override def succn(n: Int, a: Weekday) = super.succn(n % 7, a) | |
override def predn(n: Int, a: Weekday) = super.predn(n % 7, a) | |
override def min = Some(Sun) | |
override def max = Some(Sat) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment