この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
引き続き今回はContravariantをやっていきます。
Readerに対するFunctor
次のような2つの型パラメータをとる型コンストラクタReaderを考えたとき、そのFunctorの実装は以下のようになります。
タプルやEitherは2つの型パラメータを入れ替えても関手性が成り立ちますが、Readerではどうでしょう?関数の向きを反転したOpを考えたときReaderに対するFunctorは定義できますがOpに対しては定義できません。
import cats.{Functor, Contravariant}
package object chap8:
type Reader[R, A] = R => A
type Op[R, A] = A => R
given readerOpFunctor[R]: Functor[Op[R, *]] with
def map[A, B](fa: Op[R, A])(f: A => B): Op[R, B] = ???
given readerFunctor[R]: Functor[Reader[R, *]] with
def map[A, B](fa: Reader[R, A])(f: A => B): Reader[R, B] = f compose fa
ここでOpに対するContravariant Functor の実装は以下のようになります。
given readerOpContravariant[R]: Contravariant[Op[R, *]] with
def contramap[A, B](fa: Op[R, A])(f: B => A): Op[R, B] = fa compose f
Law testing
ReaderおよびOpに対するEqが定義できなかったので今回はありません……
まとめ
Readerの(Covariant) FunctorとOpのContravariantの実装が対称になっているのが双対圏における射の向きと同じになっているのが印象的でした。