2012年12月9日日曜日

Injectiveを考える

この記事はScalaz Advent Calendarの9日目の記事です。

この記事に書いてあることは役にたたないと思うので、あまり気合を入れて読まないでください。

Injective


Scalazには、Injectively, Injective1 ~ Injective5が定義されている。
よくわからない。

Injectiveをググってみると、どうやら単射のことっぽい。

Injectiveは型パラメータをとる型を型引数にとる。
つまり、種(カインド)が* -> *や、* -> * -> *である型が単射であるいう制約をつけるものではないかと考えた。

とりあえずInjectiveの例を列挙してみる。

List

def f[M[_]: Injective, A](m: M[A]) = m
object ListInjective extends Injective[List]
f(List(0))(ListInjective)
view raw list.scala hosted with ❤ by GitHub
ふつうに定義できる。

type member

Hoge#Fは未定義なので、インスタンスの供給は出来ない。

trait Hoge {
type F[A]
def f[A](a: A): F[A]
}
val optionHoge = new Hoge {
type F[A] = Option[A]
def f[A](a: A) = Option(a)
}
object HogeInjective extends Injective[Hoge#F]
/* f(optionHoge.f(0))(HogeInjective) */ // Compile Error
view raw member.scala hosted with ❤ by GitHub
dependent method types

def hogeInjective(hoge: Hoge) = new Injective[hoge.F] {}
f(optionHoge.f(0))(hogeInjective(optionHoge))
view raw depend.scala hosted with ❤ by GitHub
明示的にインスタンスを渡す必要はあるが、コンパイルすることは可能。


ふむ、よくわからない。

単射にならない型がもしあるのだとしたら、F[_]に対して、ある型Aを渡した時にコンパイルが通らないということだろうか。
ということは、F[_]がとりうる型に対して制約をかければよいということだろう。

次のような例を書いた。

trait Foo
trait Bar[F <: Foo]
/* object BarInjective extends Injective[Bar] */ // Compile Error
view raw injective.scala hosted with ❤ by GitHub
なるほど。
確かに、単射ではないからInjectiveのインスタンスが定義出来ない。

Injectiveの意味がようやく理解できた。

InjectiveはLiskovのコードで使われているが、まあ、よくわからない。
わからなくても、この先困るということもないと思う。

0 件のコメント:

コメントを投稿