Created
November 4, 2011 18:27
-
-
Save soc/1340092 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
| object UnitsTest extends App { | |
| import Units._ | |
| val length1 = m(23) | |
| val length2 = m(17) | |
| val area: Area = length1 * length2 // Works, Quantity[_2, _0] | |
| val time = s(42) | |
| // Just to show that mixing units works... | |
| val foo: Foo = time * length1 // Works, Quantity[_1, _1] | |
| // val speed: Speed = length1 / time // Doesn't work, Quantity[_1, _1#Neg] | |
| /* | |
| type mismatch; | |
| found : | |
| Units.Quantity[Subtractables.-[Integers._1,Integers._0], | |
| Subtractables.-[Integers._0,Integers._1]] | |
| required: | |
| Units.Speed | |
| */ | |
| // val lengt3: Length = length1 * length2 / length1 // Doesn't work, Quantity[_1, _0] | |
| /* | |
| type mismatch; | |
| found : | |
| Units.Quantity[Subtractables.-[Addables.+[Integers._1,Integers._1],Integers._1], | |
| Subtractables.-[Addables.+[Integers._0,Integers._0],Integers._0]] | |
| required: | |
| Units.Length | |
| */ | |
| } | |
| object Units { | |
| import Integers._ | |
| import Addables._ | |
| import Subtractables._ | |
| trait Unit { | |
| type M <: MInt | |
| type S <: MInt | |
| } | |
| final class TUnit[_M <: MInt, _S <: MInt] { | |
| type M = _M | |
| type S = _S | |
| } | |
| case class Quantity[M <: MInt, S <: MInt](value : Double) { | |
| type This = Quantity[M, S] | |
| def *[M2 <: MInt, S2 <: MInt](m : Quantity[M2, S2]) = Quantity[M + M2, S + S2](value * m.value) | |
| def /[M2 <: MInt, S2 <: MInt](m : Quantity[M2, S2]) = Quantity[M - M2, S - S2](value / m.value) | |
| def apply(v : Double) = Quantity[M, S](v * value) | |
| } | |
| val m = Quantity[_1, _0](1) | |
| val s = Quantity[_0, _1](1) | |
| type Length = Quantity[_1, _0] | |
| type Time = Quantity[_0, _1] | |
| type Area = Quantity[_2, _0] | |
| type Volume = Quantity[_3, _0] | |
| type Speed = Quantity[_1, _1#Neg] | |
| type Acceleration = Quantity[_1, _2#Neg] | |
| type Foo = Quantity[_1, _1] | |
| } | |
| object Addables { | |
| trait Addable { | |
| type AddType <: Addable | |
| type Add[T <: AddType] <: AddType | |
| } | |
| type +[A1 <: Addable, A2 <: A1#AddType] = A1#Add[A2] | |
| } | |
| object Subtractables { | |
| trait Subtractable { | |
| type SubType <: Subtractable | |
| type Sub[T <: SubType] <: SubType | |
| } | |
| type -[S1 <: Subtractable, S2 <: S1#SubType] = S1#Sub[S2] | |
| } | |
| object Comparables { | |
| import Booleans._ | |
| trait Comparable { | |
| type CompareType <: Comparable | |
| type LessThan[T <: CompareType] <: Bool | |
| } | |
| } | |
| object Booleans { | |
| sealed trait Bool { | |
| type Not <: Bool | |
| } | |
| final class True extends Bool { | |
| type Not = False | |
| } | |
| final class False extends Bool { | |
| type Not = True | |
| } | |
| } | |
| object Integers { | |
| import Visitables._ | |
| import Addables._ | |
| import Subtractables._ | |
| trait NatVisitor extends TypeVisitor { | |
| type Visit0 <: ResultType | |
| type VisitSucc[Pre <: Nat] <: ResultType | |
| } | |
| trait IntVisitor extends NatVisitor { | |
| type VisitNeg[Pos <: Nat] <: ResultType | |
| } | |
| sealed trait MInt extends Visitable[IntVisitor] with Addable with Subtractable { | |
| type AddType = MInt | |
| type SubType = MInt | |
| type Add[I <: MInt] <: MInt | |
| type Neg <: MInt | |
| type Succ <: MInt | |
| type Pre <: MInt | |
| } | |
| sealed trait Nat extends MInt { | |
| type Accept[V <: IntVisitor] = AcceptNatVisitor[V] | |
| type AcceptNatVisitor[V <: NatVisitor] <: V#ResultType | |
| } | |
| final class _0 extends Nat { | |
| type Add[I <: MInt] = I | |
| type AcceptNatVisitor[V <: NatVisitor] = V#Visit0 | |
| type Neg = _0 | |
| type Succ = MSucc[_0] | |
| type Pre = Succ#Neg | |
| } | |
| sealed trait Pos extends Nat | |
| final class MSucc[P <: Nat] extends Pos { | |
| type This = MSucc[P] | |
| type Add[N <: MInt] = P#Add[N]#Succ | |
| type AcceptNatVisitor[V <: NatVisitor] = V#VisitSucc[P] | |
| type Neg = MNeg[This] | |
| type Pre = P | |
| type Succ = MSucc[This] | |
| } | |
| final class MNeg[N <: Pos] extends MInt { | |
| type Add[N <: MInt] = N#Add[N#Neg]#Neg | |
| type Accept[V <: IntVisitor] = V#VisitNeg[N] | |
| type Neg = N | |
| type Succ = N#Pre#Neg | |
| type Pre = N#Succ#Neg | |
| } | |
| type _1 = MSucc[_0] | |
| type _2 = MSucc[_1] | |
| type _3 = MSucc[_2] | |
| val _0 = new _0 | |
| val _1 = new _1 | |
| val _2 = new _2 | |
| val _3 = new _3 | |
| } | |
| object Nats { | |
| import Utils._ | |
| import Booleans._ | |
| import Addables._ | |
| import Comparables._ | |
| import Visitables._ | |
| trait NatVisitor extends TypeVisitor { | |
| type Visit0 <: ResultType | |
| type VisitSucc[Pre <: Nat] <: ResultType | |
| } | |
| sealed trait Nat extends Addable with Comparable { | |
| type CompareType = Nat | |
| type Pre | |
| type Is0 <: Bool | |
| type Add[T <: Nat] <: Nat | |
| type AddType = Nat | |
| type Accept[N <: NatVisitor] <: N#ResultType | |
| type Equals[N <: Nat] <: Bool | |
| type LessThan[N <: Nat] <: Bool | |
| def toInt : Int | |
| } | |
| final class _0 extends Nat { | |
| type Pre = Invalid | |
| type Is0 = True | |
| type Add[N <: Nat] = N | |
| type Accept[N <: NatVisitor] = N#Visit0 | |
| type Equals[N <: Nat] = N#Is0 | |
| type LessThan[N <: Nat] = N#Is0#Not | |
| def toInt = 0 | |
| } | |
| final case class Succ[P <: Nat](toInt : Int) extends Nat { | |
| type Pre = P | |
| type Is0 = False | |
| type Add[N <: Nat] = Succ[P#Add[N]] | |
| type Accept[N <: NatVisitor] = N#VisitSucc[P] | |
| trait EqualsVisitor extends NatVisitor { | |
| type ResultType = Bool | |
| type Visit0 = False | |
| type VisitSucc[Pre <: Nat] = P#Equals[Pre] | |
| } | |
| type Equals[N <: Nat] = N#Accept[EqualsVisitor] | |
| trait LessThanVisitor extends NatVisitor { | |
| type ResultType = Bool | |
| type Visit0 = False | |
| type VisitSucc[Pre <: Nat] = P#LessThan[Pre] | |
| } | |
| type LessThan[N <: Nat] = N#Accept[LessThanVisitor] | |
| def +[N <: Nat](n : N) : Add[N] = Succ[P#Add[N]](toInt + n.toInt) | |
| } | |
| type _1 = Succ[_0] | |
| type _2 = Succ[_1] | |
| type _3 = Succ[_2] | |
| val _0 = new _0 | |
| val _1 = new _1(1) | |
| val _2 = new _2(2) | |
| val _3 = new _3(3) | |
| } | |
| object Visitables { | |
| trait TypeVisitor { | |
| type ResultType | |
| } | |
| trait Visitable[V <: TypeVisitor] { | |
| type Accept[V2 <: V] <: V2#ResultType | |
| } | |
| } | |
| object Utils { | |
| final class Invalid | |
| case class TypeToValue[T, VT](value : VT) { | |
| def apply() = value | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment