この記事はScala Advent Calendar 2015(Adventar)の9日目の記事です。
Scalaには、型クラスを実現するための仕組みとしてimplicit parameterという仕組みがあります。これとimplicit conversionを組み合わせることによって、オーバーロードやinterfaceでは実現できないようなオープンな演算の定義と安全性を両立させることができます。
このあたりの話はhttp://nekogata.hatenablog.com/entry/2014/06/30/062342 などを参照してください。
Scalaの怖いライブラリの代表格として、Scalazというものがあり、ここでは様々な便利な型クラスが定義されています。たとえばそのなかのひとつに「Order型クラス」が存在します。
このOrder型クラスは、「順序があるよ」という性質を表した型クラスになっており、scala標準の型でも、Stringなど様々なクラスがこの型クラスのインスタンスにされています。
また、Order型のインスタンスになることで、implicit conversion経由で "<" や ">" などの便利メソッドが使えるようになります。
たとえば JodaTime を利用しているとき、AbstractInstantなインスタンス を > や < で比較できたら便利だなー、などと思ったとします。AbstractInstantな型をOrder型クラスのインスタンスにしてしまえば実現できそうですね。実際にやってみましょう。
見てのとおり、orderメソッドだけ実装されていないtraitがその実態です。ということは、orderメソッドを実装したAbstractInstantOrder[A <: AbstractPartial] extends Order[A]なオブジェクトへのimplicit conversionを定義してやれば、DateTimeなどのAbstractInstantのサブクラスのインスタンスを < や > で比較できるようになるはずです。(このへんの理屈がわからない場合は、しつこいようですがhttp://nekogata.hatenablog.com/entry/2014/06/30/062342 を参照してください)
自分でがんばってobject AbstractInstantOrder[A <: AbstractInstant] extends Order[A]を定義して、それへのimplicit conversionを定義してもいいのですが、Order.scalaを読んでいたらこんな便利なメソッドを見つけました。order[Nyan] {(a, b) => ???}としてやれば、new NyanOrder extends Order[Nyan]{ def order(a: Nyan, b: Nyan) = ??? }を返してくれる便利なやつです。こいつとimplicit conversionを組み合わせてAbstractInstantな型をOrder型クラスのインスタンスにしてやると、こんなかんじになります。
object JodaTimeOrder { implicit def JodaTimeInstantOrder[A <: AbstractInstant]: Order[A] = order { (a, b) =>if (a.isBefore(b)) scalaz.Ordering.LTelseif (a.isEqual(b)) scalaz.Ordering.EQelse scalaz.Ordering.GT }}
これで、JodaTimeのAbstractInstantなクラスすべてを、Order型クラスのインスタンスにすることができました!使うときには、以下のようなかんじになります。
import JodaTimeOrder._import scalaz.Scalaz._if (dateTimeInstanceA < dateTimeInstanceB) {// Bのほうが後の日時}else {// Bのほうが後の日時ではない}
自分で書き換えることのできないようなクラスも、ちょっとしたグルーコードを書いてやることで型クラスのインスタンスのしてやることができましたね!
既存のクラスをScalazの型クラスのインスタンスにする例を見てみました。Scalazのコードを読みながら「なるほどこうやればいいんだな」みたいなかんじでやっていけばできることではあるのですが、「わざわざコード読まなくてもここに書いてあるよ」みたいな情報を知っているひとがあればぜひ教えてください。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。