Enforce usage of aliased type in Scala

deamon

Is it possible in Scala to create something like type aliases that can be used to enforce certain conditions? Yes, I know, this sounds somewhat strange, but let me illustrate what I mean.

Let's say we want to have only positive Integers of the type java.lang.Integer. This class does of course allow also negative integers, so it wouldn't be sufficient to use this type in cases where only positive integers are allowed. My vague idea is to have something like an "enforced type alias".

// vague idea
object PositiveInteger {
  import java.lang.{Integer, Math}
  type PositiveInteger = Integer // something like this, but enforced
  def apply(value: Int) = new PositiveInteger(Math.abs(value))
}

And then I want do be able to define parameters and values of the type PositiveInteger and relying on the fact that they are positive:

def calculate(value: PositiveInteger) = ...

I want to avoid wrapping the class within another (value) class, because I would need to repeat all the methods or always access a field holding the wrapped object from the outside.

As far as I know, that wouldn't be possible in Scala, but maybe you know a way to achieve this. Do you?

volia17

You can use this technique from scalaz, to add a tag on a type (http://eed3si9n.com/learning-scalaz/Tagged+type.html)

// Entering paste mode (ctrl-D to finish)

  type Tagged[U] = {type Tag = U }
  type @@[T, U] = T with Tagged[U]

  object Tag {
    @inline def apply[T, U](t : T) : T @@ U = t.asInstanceOf[T @@ U]
  }

  sealed trait PositiveInt
  object PositiveInt {
    def apply(i : Int) : Int @@ PositiveInt = Tag(Math.abs(i))
    def unapply(p : Int @@ PositiveInt) : Option[Int] = Some(p)
  }

  // Exiting paste mode, now interpreting.

And the result is :

defined type alias Tagged
defined type alias $at$at
defined object Tag
defined trait PositiveInt
defined object PositiveInt

scala> PositiveInt(4)
res0: @@[Int,PositiveInt] = 4

scala> PositiveInt(-4)
res1: @@[Int,PositiveInt] = 4

scala> res0 + res1
res2: Int = 8

But this solution is not perfect.

scala> PositiveInt(5) - PositiveInt(6)
res4: Int = -1


scala> PositiveInt(PositiveInt(5) - PositiveInt(6))
res5: @@[Int,PositiveInt] = 1

To get full solution, you may have to get a real class with full method definition

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related