Making connections between types and values

后端 未结 2 1473
伪装坚强ぢ
伪装坚强ぢ 2021-01-16 14:10

I have implementations of type-level arithmetics capable of doing some compile time arithmetic validation, namely <,>,= in two ways:

  • simple
相关标签:
2条回答
  • 2021-01-16 15:00

    The answer seems to be just "No". The values exist at runtime. The type checking happens at compile time. These two time intervals do not intersect, the runtime always comes strictly after the compile time, so there is no way to propagate the information about a value back in time to obtain some additional information about a type.

    Note that if an ordering is all you want (you don't want to add or subtract version numbers), then you can simply reuse the subtyping relation as follows:

    sealed trait Num
    class _9 extends Num
    class _8 extends _9
    class _7 extends _8
    class _6 extends _7
    class _5 extends _6
    class _4 extends _5
    class _3 extends _4
    class _2 extends _3
    class _1 extends _2
    class _0 extends _1
    
    trait Version[+Major <: Num, +Minor <: Num]
    
    println(implicitly[Version[_2, _4] =:= Version[_2, _4]])
    println(implicitly[Version[_2, _3] <:< Version[_2, _4]])
    
    0 讨论(0)
  • 2021-01-16 15:12

    The trick is to realise that values can have type fields and that type information is available at compile time. With this in mind, we can define:

    sealed trait NatEnum{
      type Nat_ <:Nat
    }
    

    and define enum "values" for these types like:

    object __0 extends NatEnum{ override type Nat_ = _0 }
    object __1 extends NatEnum{ override type Nat_ = _1 }
    object __2 extends NatEnum{ override type Nat_ = _2 }
    object __3 extends NatEnum{ override type Nat_ = _3 }
    

    and refactor getFoo as below:

    def getFoo(maj: NatEnum, min: NatEnum)(implicit
                         maj_check: FooClient.Major =:= maj.Nat_,
                         min_check: FooClient.Minor <:< min.Nat_
                        ) = FooClient.foo
    

    which we can test with:

    getFoo(__2,__2) //compiles
    getFoo(__1,__0)// doesn't compile
    

    here is the updated version of the gists: simple and rigorous

    0 讨论(0)
提交回复
热议问题