Type safe Scala โ€” Tagged types

Jun 19, 2017
functional-programming
scala

๐Ÿ”–

Today letโ€™s talk about briefly about tagged types. A tagged type is useful when the type youโ€™re working with is completely valid for your domain of application but still you want to add extra information to the type just as we did with phantom type parameters .

For example, letโ€™s take the situation where we have to send information to some service, but the information needs to be protected with an ephemeral key. java.security.Key is perfectly valid, but we can use tagged types to encode the fact that the key is ephemeral, and use that information whenever we need to check we are indeed using an ephemeral key:

import java.security.Key
import javax.crypto.KeyGenerator
import tag.Tagged
sealed trait Ephemeral // phantom type used to tag
def generateKey: Tagged[Key, Ephemeral] = {
val gen = KeyGenerator.getInstance("AES")
gen.init(128) // Block size
tag(gen.generateKey)
}

The implementation for tagging types is really simple:

object tag {
sealed trait Tag[U]
type Tagged[T, U] = T with Tag[U]
def apply[T, U](value: T): Tagged[T, U] =
value.asInstanceOf[Tagged[T, U]]
}

And the magic resides in that Tagged[T, U] is a subtype of T : implicitly[Tagged[T, U] <:< T] will yield a value for any T and U. Whenever we need T, we can just use the tagged type variant, but if instead we need Tagged[T, U], we cannot pass T without the required tag.

Take a look at how tagged types are implemented in shapeless , there they use @@ instead of Tagged and a class Tagger to benefit from type inference when tagging: tag Ephemeral instead of tag[Key, Ephemeral](key) as it would be in our example if we couldnโ€™t use the inference of the return type of our generateKey function.