LoginSignup
9
9

More than 5 years have passed since last update.

TaggedTypes

Last updated at Posted at 2016-02-12

TaggedTypesを使うと、型にメタ情報を与えることができる。

例えば以下の例だと、Person#name, Company#nameが同じくString型なので、両者を混同してしまう可能性がある。

case class Person(name: String)
case class Company(name: String)
def findCompanyByName(companyName: String): Option[Company] = ???

val person = Person("John")
findCompanyByName(person.name)  // 当たり前だが、コンパイルできる

ここで、こういった型エイリアスを定義しておくと、

Tagged.scala
type Tagged[T] = {type Tag = T}
type @@[+T, Tag] = T with Tagged[Tag]
def tagged[T, Tag](a: T): T @@ Tag = a.asInstanceOf[T @@ Tag]

以下のように「Person用のStringである」ことを表せて、しかも間違えた時にコンパイルエラーにできる。
これをTaggedTypesという。
TaggedTypesの実装方法はいくつかあって、上にあげたのはscalaz 7.0.xで使われている方法。
scalaz 7.1以降からは実装方法が変わっている。(https://github.com/scalaz/scalaz/pull/693)

case class Person(name: String @@ Person)
case class Company(name: String @@ Company)
def findCompanyByName(companyName: String @@ Company): Option[Company] = ???

val person = Person(tagged("John"))
val company = Company(tagged("opt"))
findCompanyByName(person.name)  // 通らない
findCompanyByName(company.name) // 通る

また、この方法で実装したTaggedTypesでは以下のようなことができる(scalaz 7.1以降ではできない)

  • もとの型のメソッドがよべる
val x: String @@ X = tagged("x")
x.split(",") // よべる
  • Stringとして扱える
val x: String @@ X = tagged("x")
def foo(a: String): Unit = ???
foo(x)  // 通る

参考

がくぞさんのスライドがわかりやすい
http://gakuzzzz.github.io/slides/refactoring_in_scala/#1

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9