設計が大幅に変わったので6系にべったりだと移行はかなり大変な気がします。
Tagged
Scalaz7ではNewTypeがなくなり、代わりにTagged Typesというものが入りました。
これは既存の型にタグを付けることで、コンパイラに別の型のように見せることができます。
さらに、この型は元の型が必要な場合にはunboxされるという素敵なものです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Foo | |
type Bar = Int @@ Foo |
@@がタグを付けるためのものです。
ここではIntにFooタグを付けたものをBarとしました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val bar: Bar = Tag[Int, Foo](100) | |
lazy val f: Bar => Int = 100 |+| _ | |
f(bar) assert_=== 200 | |
// f(100) Error |
この型を取る関数にIntを渡すとコンパイルエラーになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val foobar: Long @@ Foo = Tag(10) | |
lazy val g: Long @@ Foo => Long = 100L |-| _ | |
g(foobar) assert_=== 90L | |
type Baz[T] = T @@ Foo | |
val baz: Baz[String] = Tag("Scalaz") | |
lazy val h: Baz[String] => String = (_: String).multiply(2) | |
h(baz) assert_=== "ScalazScalaz" |
エイリアス付けるとTagを使ったときに推論が効かないので、@@を直接書くか、型パラメータをとるようにするといいです。
Scalaz7ではNewTypeを使っていた殆どはTagged Typesに置き換えられました。
あまりなにも考えずNewTypeばかり継承していると移行が大変ですのでこのことも考えておきましょう。 (体験者談)
Tagged Typesについて詳しく知りたい場合はこちらを。
Union
最近入って、SNAPSHOTにもまだ入ってないもの。
型の和が簡単に作れてしまう優れもの。
これもunboxされる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Hoge = UnionTypes.t[Int]#t[String] | |
type Huga = UnionTypes.t[Long]#t[Double] |
t[A]#t[B]でAとBの和を作ります。
この型を直接引数に取るのではなく、Containsという型を使います。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def f[T](t: T)(implicit ev: UnionTypes.Contains[T, Hoge]): Int = t match { | |
case i: Int => i | |
case s: String => s.length | |
} | |
f(100) assert_=== 100 | |
f("Scalaz7") assert_=== 7 | |
// f(10.05) Error | |
val huga: UnionTypes.Union[Huga] = Converter(0.5).union | |
huga.value.asInstanceOf[Double] assert_=== 0.5 |
Converterで値を持てるけど、Anyになってしまうので微妙。
Tagged Typeにも言えますが、Unionはsealed traitとcase classで新しいデータ構造を作るより手軽に使えるところがいいところですね。
Scalaz7は全体的に効率化がされていて、Unboxedなこれらの型もそのためにあるのだと思います。
便利な上に効率もいいのでガンガン使ってしまいましょう。
早くScalaz7が出て欲しいなぁ。
※追記
現在、Tagはspecializedアノテーションが付いているけど、実は機能していないということを教えて頂きました。
Scalazがプリミティブ全部にTagを用意するのか、Scalaのspecializedが良くなるのか、それともそのままなのか、Scalaz7がリリースされるまではわかりません。
Scalaz7のリリースはScala Daysの日になるかも・・・・・?
0 件のコメント:
コメントを投稿