Skip to content

Instantly share code, notes, and snippets.

@tpolecat
Last active December 20, 2015 22:38
Show Gist options
  • Save tpolecat/6205985 to your computer and use it in GitHub Desktop.
Save tpolecat/6205985 to your computer and use it in GitHub Desktop.
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