case class Person(id: Long, name: String, organizationId: Long)
object Person {
def groupByOrg: Map[Long, Seq[Person]] = ...
}
- wrap/unwrapが存在しない
- Boxing/Unboxingが発生しない
- 大抵のDBライブラリやJSONライブラリなどでそのまま扱える
- 定義が楽
- 型安全でない
- シグネチャだけで意味が取れない
package object models {
type PersonId = Long
type PersonName = String
type OrganizationId = Long
}
case class Person(id: PersonId, name: PersonName, organizationId: OrganizationId)
object Person {
def groupByOrg: Map[OrganizationId, Seq[Person]] = ...
}
- wrap/unwrapが存在しない
- Boxing/Unboxingが発生しない
- 大抵のDBライブラリやJSONライブラリなどでそのまま扱える
- シグネチャだけで意味がわかりやすい
- 型安全でない
- 定義が手間
case class PersonId(value: Long) extends AnyVal
case class PersonName(value: String) extends AnyVal
case class OrganizationId(value: Long) extends AnyVal
case class Person(id: PersonId, name: PersonName, organizationId: OrganizationId)
object Person {
def groupByOrg: Map[OrganizationId, Seq[Person]] = ...
}
- 型安全
- シグネチャだけで意味がわかりやすい
- 特定のケースを除いてwrap/unwrap時にオーバーヘッドが存在しない
- Boxing/Unboxingが発生しない
- メソッドが定義しやすい
- 定義が手間
- DBライブラリやJSONライブラリなどで変換ロジックを書く必要がある
- 特定のケースでオーバーヘッドが存在する
import scalaz._
import scalaz.Tag._
package object models {
type Id = Long
type Name = String
}
case class Person(id: Id @@ Person, name: Name @@ Person, organizationId: Id @@ Organization)
object Person {
def groupByOrg: Map[Id @@ Organization, Seq[Person]] = ...
val tagOf: TagOf[Person] = Tag.of[Person]
}
- 型安全
- シグネチャだけで意味がわかりやすい
- wrap/unwrap時にオーバーヘッドが存在しない
- 定義が楽
- DBライブラリやJSONライブラリなどで変換ロジックを書く必要がある
- Boxing/Unboxingが発生する
メリット | デメリット | |
---|---|---|
primitive 型 | * wrap/unwrapが存在しない * Boxing/Unboxingが発生しない * 大抵のDBライブラリやJSONライブラリなどでそのまま扱える * 定義が楽 |
* 型安全でない * シグネチャだけで意味が取れない |
type alias | * wrap/unwrapが存在しない * Boxing/Unboxingが発生しない * 大抵のDBライブラリやJSONライブラリなどでそのまま扱える * シグネチャだけで意味がわかりやすい |
* 型安全でない * 定義が手間 |
値クラス | * 型安全 * シグネチャだけで意味がわかりやすい * 特定のケースを除いてwrap/unwrap時にオーバーヘッドが存在しない * Boxing/Unboxingが発生しない * メソッドが定義しやすい |
* 定義が手間 * DBライブラリやJSONライブラリなどで変換ロジックを書く必要がある * 特定のケースでオーバーヘッドが存在する |
TaggedType | * 型安全 * シグネチャだけで意味がわかりやすい * wrap/unwrap時にオーバーヘッドが存在しない * 定義が楽 |
* DBライブラリやJSONライブラリなどで変換ロジックを書く必要がある * Boxing/Unboxingが発生する |
@mauhiz
今の Scalaz の TaggedType は昔と違って Shapeless の newtype と同じように元クラスのメソッドが呼べないようになってるのでやってる事は殆ど一緒ですね。
TaggedTypeに比べて追加でメソッドを生やすのが多少楽に書けるようになっている、ぐらいの認識です。
@xuwei-k
あ、値の作成時のオーバーヘッドしか気にして無くてBoxing/Unboxingのコスト忘れてました。
こちら足しますね。
ありがとうございます。
https://github.com/scalaz/scalaz/blob/6e807315ecbb925e0085310c5955640fee39da78/core/src/main/scala/scalaz/Tag.scala#L8 悲しい