ScalaのFPファンクタヌずは

関数型プログラミングの研究を開始する専門家は、甚語のあいたいさず耇雑さの䞡方に盎面し、「深刻な数孊」ぞの蚀及を垞に受け​​おいたす。



この蚘事では、カテゎリ理論ずScalaの難解な蚀語メカニズムを䜿甚せずに、2぀の重芁な抂念を怜蚎したす。

含めるこずができるカテゎリ構造のセット党䜓を理解するための出発点です



カテゎリヌ甚語の起源に぀いお説明し、カテゎリヌ抜象化の実装における蚀語メカニズムの圹割を瀺し、Scala暙準ラむブラリヌからのいく぀かの共倉 Option 、 Try 、 Future 、 List 、 Parser および反倉ファンディング 、 Equiv ファンクタヌを怜蚎したす。



「カテゎリシリヌズ」の最初の蚘事

  1. ScalaのFPファンクタヌずは
  2. ScalaのFPInvariant Functor


Scala、数孊、関数型プログラミングの䞖界をさらに詳しく知りたい堎合は、 Scala for Java Developersオンラむンコヌスをお詊しくださいビデオ+テスト、䟡栌のわずか25。







抜象化の蚀語メカニズムに぀いお



基本的に新しいプログラミング蚀語ぞの没入には、以䞋の孊習が含たれたす。

  1. 新しいタむプの抜象化のための蚀語メカニズム。
  2. これらのタむプの抜象化が䜿甚される兞型的なむディオム/パタヌン。


䟋OOPは、クラス、むンスタンス、継承、ポリモヌフィズム、カプセル化、委任、...およびGoF蚭蚈パタヌンの抂念を調査したす。この蚭蚈パタヌンでは、このようなさたざたな抜象化メカニズムがすべお䜿甚されたす。



私の意芋では、移行Java => Scalaの䞻な問題は、プログラマヌが新しい抜象化メカニズムより高い皮類のゞェネリック、パス䟝存型、型クラス、マクロなどを孊習しないこずです。 。



そしお、「抜象化の察象」ファンクタヌ、モナド、モノむド、埓属型などの話が始たるずすぐに、珟代数孊カテゎリヌ理論、抜象代数、数理論理孊の理論家が珟れ、 「ボヌドからすべおのピヌスをひっくり返したす。」 プログラマヌの芳点からは、数孊者はしばしば、カテゎリヌの到来の蚌人掟/型のホモトピヌ理論/構成の蚈算の狂信者のように振る舞いたす「私たちの蚀語で」ず蚀っおプログラミングの分野から具䜓的な䟋を䞎えるのではなく、圌らは抜象数孊の芳点から泚いで、圌らの聖人を参照したすテキスト



この蚘事では、ファンクタヌ共倉および反倉は、カテゎリヌ理論に頌らずに基本的なScalaの特城のみに基づいお分析されたす。 より高い皮類の 型クラスずゞェネリックは䜿甚されたせんたずえば、 Scalazラむブラリの䜜成者は、 scala.scalaz.Functor + scala.scalaz.Contravariant 、Cats scala.cats.Functor + cats.functor.Contravariant 、Algebird com。 twitter.algebird.Functor 。 倚くの堎合、むディオムの共倉ファンクタヌず反倉ファンクタヌに察応する型の名前では、省略名ファンクタヌず反倉が䜿甚されるこずに泚意しおください。



䞀般的に、Scalaの関数型プログラミングL2〜L3レベルは、Javaに察しおいく぀かの方向のオフセットです3぀参照。 さらに、オフセットは4぀の「コンポヌネント」によっお同時に特城付けられたす。

  1. 新しいプログラミングテンプレヌト/むディオム/真珠。
  2. これらのむディオムを実装するためのScalaの新しい蚀語゚ンゞン。
  3. 蚀語メカニズムに基づくむディオムの実装を備えた新しいScalaラむブラリ。
  4. むディオムの重芁なアむデアの゜ヌスずしお機胜した数孊の新しいセクション。


それに泚意する必芁がありたす



少なくずも、「3぀のシフト」を区別できたす。カテゎリヌ、代数、論理数孊のセクションの名前による

むディオムFP Scalaギア Scalaラむブラリ 数孊のセクション
共倉ファンクタヌ、適甚ファンクタヌ、モナド、矢印 型クラス、䞊䜍のゞェネリック スカラズ、猫 カテゎリヌ理論
䟝存ペア、䟝存関数 パス䟝存型 圢のない 数孊的論理
モノむド、グルヌプ、フィヌルド、リング 型クラス、䞊䜍のゞェネリック アルゞバヌド、スパむア 代数


芁するに



私たちの䟋では、より高いking +型クラスのゞェネリックを䜿甚しないため、再利甚に適合したせんそしお、ここでの「叀き良きOOPトリック」は特に適しおいたせん。 しかし、再利甚の準備ができおいなくおも、この䟋はむディオムの本質をよく瀺しおいたす。





カテゎリヌ理論ずHaskellに぀いお



20䞖玀半ばに、数孊の新しい分野が生たれたした-カテゎリヌ理論数孊者自身がしばしば「抜象的なナンセンス」ず呌ぶこずに泚意しおください。 カテゎリ理論は、数孊の倚くの基本領域集合論、トポロゞヌ、機胜分析などで広く䜿甚されおいる䞀般的なアむデア/構造から来おおり、珟圚、すべおの数孊の基瀎/基盀であるず䞻匵しおいたす構築した集合論の矀集 20䞖玀初頭からの数孊。



しかし、集合論が集合自䜓芁玠、集合の操䜜、集合のカヌディナリティ、構造を持぀集合順序付き集合、郚分順序集合などに焊点を合わせおいる堎合、集合のマッピング集合から集合ぞの関数は背景にあり、カテゎリヌ理論では、基瀎はカテゎリヌですが、簡単に蚀えば、 category = set + mappingsです。 マッピングは関数の同矩語ですより正確には、マッピング=匕数から倀に盎接「移動」する手順を指定せずに倀のドメむンの芁玠の定矩のドメむンの芁玠に察応、マッピング=テヌブルで指定された関数、マッピング= fの意味の関数の「倖郚むンタヌフェむス」 A => B 「内郚実装」関数本䜓を指定せずに、ここで、関数自䜓のような匷調は、関数型プログラミングにずっお非垞に重芁であるこずがわかりたす。



マッピングに集䞭するず、豊富な機胜的抜象化ファンクタヌ、モナドなどが発生し、これらの抜象化は関数型プログラミング蚀語Haskellで最も有名な実装に転送されたした。 Scalaの倜明け2005幎から2010幎はHaskellの倜明け1990幎から1995幎に比べお15幎間盞殺され、倚くのこずはHaskellからScalaに既補で転送されたす。 したがっお、Scalaプログラマヌにずっおは、カテゎリヌ理論自䜓ではなく、カテゎリヌ抜象化の䞻な゜ヌスずしおHaskellの実装を扱うこずがより重芁です。 これは、カテゎリヌ理論=> Haskellの転送䞭に、倚くの重芁な詳现が倉曎、消倱、たたは远加されたずいう事実によるものです。 プログラマヌにずっお重芁ですが、数孊者にずっおは二次的なものです。



移行の䟋を次に瀺したす。

  1. カテゎリヌ理論
  2. ハスケル
  3. ScalaScalazラむブラリ




共倉ファンクタヌずは



䞀郚の著者は、 Covariant Functorをコンテナヌにするこずを掚奚しおいたす より正確には、共倉Functorはむしろ「コンテナヌの半分」です。 この比phorを思い出すこずをお勧めしたすが、定矩ではなく比preciselyずしお正確に扱いたす。



Covariant Functorが「蚈算コンテキスト」である他の人 。 これは生産的なアプロヌチですが、コンセプトを完党にマスタヌし、「最倧限に掻甚しよう」ずする堎合に圹立ちたす。 今のずころ無芖しおください。



さらに他の人は、「より構文的なアプロヌチ」を提案しおいたす。 Covariant Functorは、特定のメ゜ッドを持぀特定のタむプです。 メ゜ッドは特定のルヌル2぀に準拠する必芁がありたす。



「構文アプロヌチ」を䜿甚し、コンテナ/ストレヌゞのメタファヌを䜿甚するこずをお勧めしたす。



「構文的アプロヌチ」の芳点から芋るず、共倉ファンクタヌは、次のシグネチャを持぀メ゜ッド mapず呌ぶを持぀型パラメヌタヌを持぀任意の型 Xず呌ぶを持぀型です。

trait X[T] { def map(f: T => R): X[R] }
      
      





重芁この特性から継承するのではなく、類䌌のタむプを探したす。



「構文的アプロヌチ」は、倚くのカテゎリ構造を䞀般的なスキヌムにたずめるこずができるずいう点で優れおいたす

 trait X[T] { // covariant functor (functor) def map[R](f: T => R): X[R] // contravariant functor (contravariant) def contramap[R](f: R => T): X[R] // exponential functor (invariant functor) def xmap[R](f: (T => R, R => T)): X[R] // applicative functor def apply[R](f: X[T => R]): X[R] // monad def flatMap[R](f: T => X[R]): X[R] // comonad def coflatMap[R](f: X[T] => R): X[R] }
      
      





重芁ここに瀺されおいるメ゜ッドは、いく぀かの抜象化に必芁なもの共倉/反倉/指数関数ず、他適甚関数、モナド、コモナに必芁なメ゜ッドの1぀です。





共倉ファンクタヌの䟋



既にScalaたたはJava 8でプログラミングを開始しおいる人は、すぐに共倉ファンクタヌである倚くの「コンテナヌタむプ」に名前を付けるこずができたす。



オプション

 import java.lang.Integer.toHexString object Demo extends App { val k: Option[Int] = Option(100500) val s: Option[String] = k map toHexString }
      
      





たたは人生に少し近い

 import java.lang.Integer.toHexString object Demo extends App { val k: Option[Int] = Map("A" -> 0, "B" -> 1).get("C") val s: Option[String] = s map toHexString }
      
      







お詊しください

 import java.lang.Integer.toHexString import scala.util.Try object Demo App { val k: Try[Int] = Try(100500) val s: Try[String] = k map toHexString }
      
      





たたは人生に少し近い

 import java.lang.Integer.toHexString import scala.util.Try object Demo extends App { def f(x: Int, y: Int): Try[Int] = Try(x / y) val s: Try[String] = f(1, 0) map toHexString }
      
      







未来

 import java.lang.Integer.toHexString import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future object Demo extends App { val k: Future[Int] = Future(100500) val s: Future[String] = k map toHexString }
      
      





たたは人生に少し近い

 import java.lang.Integer.toHexString import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future object Demo extends App { def calc: Int = (0 to 1000000000).sum val k: Future[Int] = Future(calc) val s: Future[String] = k map toHexString }
      
      







䞀芧

 import java.lang.Integer.toHexString object Demo extends App { val k: List[Int] = List(0, 42, 100500) val s: List[String] = k map toHexString }
      
      







パヌサヌ

 import java.lang.Integer.toHexString import scala.util.parsing.combinator._ object Demo extends RegexParsers with App { val k: Parser[Int] = """(0|[1-9]\d*)""".r ^^ { _.toInt } val s: Parser[String] = k map toHexString println(parseAll(k, "255")) println(parseAll(s, "255")) } >> [1.4] parsed: 255 >> [1.4] parsed: FF
      
      







䞀般に、䟋ずしお刀断するず、コンテナずしおの共倉ファンクタヌの比phorは機胜したす。 本圓に





共倉ファンクタヌは、特定のシグネチャを持぀メ゜ッドの存圚だけでなく、2぀のルヌルの履行でもありたす。 ここでの数孊者は通垞カテゎリヌ理論を参照し、これらの芏則はファンクタヌがカテゎリヌ準同型であるずいう事実の結果であるず蚀いたす。぀たり、構造を保持するカテゎリヌぞのカテゎリヌのマッピングですそしお単䞀矢印芁玠はカテゎリヌ構造の䞀郚です恒等則芏則および矢印の構成芏則構成法。



このアプロヌチは、䞀般的にプログラミングでは非生産的です。 関数型プログラミングでは、機胜を維持しながら通垞は最適化の目的でプログラムを倉換するために、これら2぀のルヌルが必芁であるこずを考慮しおください。





共倉関数アむデンティティ法



共倉の楜しいファンクタヌの堎合、次のルヌルIdentityLaw.case0funを同䞀に実行する必芁がありたす-IdentityLaw.case1funず同じです。

 object IdentityLaw { def case0[T](fun: Functor[T]): Functor[T] = identity(fun) def case1[T](fun: Functor[T]): Functor[T] = fun.map(identity) }
      
      





ここで、identityはPredef.scalaからの倚態的な同䞀性関数単䜍関数です

 object Predef ... { def identity[A](x: A): A = x ... }
      
      





かなり簡単に-fun.mapidentityはファンクタヌ内の䜕も倉曎すべきではありたせん。



これは、バヌゞョンを保存し、各ディスプレむでバヌゞョンを増やすコンテナが、共倉ファンクタヌの䞊䜍に察応しないこずを意味したす

 //  -    class Holder[T](value: T, ver: Int = 0) { def map[R](f: T => R): Holder[R] = new Holder[R](f(value), ver + 1) }
      
      





衚瀺操䜜の回数を「カりント」するためアむデンティティ関数による衚瀺も。



しかし、このようなコヌドはファンクタヌの最初のルヌルに察応しおいたす2番目のルヌルにも察応しおいたす。

 //  -   class Holder[T](value: T, ver: Int = 0) { def map[R](f: T => R): Holder[R] = new Holder[R](f(value), ver) }
      
      





ここでは、バヌゞョンはデヌタに単玔に添付され、衚瀺時に垞に付随したす。





共倉ファンクタヌ合成法



共倉ファンクタヌ 'fun [T]'および関数 'f'および 'g'の堎合、次のルヌルCompositionLaw.case0funを同䞀に実行する必芁がありたす-CompositionLaw.case1funず同じです。

 object Lawompose extends App { def case0[T, R, Q](fun: Functor[T], f: T => R, g: R => Q): Functor[Q] = (fun map f) map g def case1[T, R, Q](fun: Functor[T], f: T => R, g: R => Q): Functor[Q] = fun map (f andThen g) }
      
      





぀たり、関数「f」で、次に関数「g」で順番に衚瀺される任意のファンクタヌコンテナヌは、関数fずgf andThen gの新しい関数構成を䜜成し、それを1回衚瀺するこずず同等です。



䟋を考えおみたしょう。 コンテナヌはしばしばファンクタヌず芋なされるため、ファンクタヌを再垰的なデヌタ型バむナリツリヌ型コンテナヌにしたしょう。

 sealed trait Tree[T] { def map[R](f: T => R): Tree[R] } case class Node[T](value: T, fst: Tree[T], snd: Tree[T]) extends Tree[T] { def map[R](f: T => R) = Node(f(value), fst map f, snd map f) } case class Leaf[T](value: T) extends Tree[T] { def map[R](f: T => R) = Leaf(f(value)) }
      
      







ここで、mapメ゜ッドfT => Rは、関数 'f'を各リヌフたたはノヌドリヌフ、ノヌドのタむプ 'T'の芁玠に適甚し、ノヌドノヌドの子孫に再垰的に䌝播したす。 だから私たちは





マッピング䞭にツリヌの構造を倉曎しようずするず、䞡方の芏則に違反したすIdentity LawずComposition Lawの䞡方。



ファンクタではありたせん各ノヌドの子孫を衚瀺するずきにスワップしたす

 case class Node[T](value: T, fst: Tree[T], snd: Tree[T]) extends Tree[T] { def map[R](f: T => R) = Node(f(value), snd map f, fst map f) }
      
      







ファンクタではありたせんディスプレむごずにツリヌが成長し、葉が枝に倉わりたす

 case class Leaf[T](value: T) extends Tree[T] { def map[R](f: T => R) = Node(f(value), Leaf(f(value)), Leaf(f(value))) }
      
      







このような誀ったバむナリツリヌの実装をファンクタヌずしお芋るず、デヌタの衚瀺ずずもに、ツリヌの構造を倉曎する圢でmapの䜿甚回数もカりントしおいるこずがわかりたす。 それで、アむデンティティに反応し、fずgのいく぀かの䜿甚法は、fずgの䜿甚法ずは異なりたす。





共倉ファンクタヌ最適化に䜿甚





共倉ファンクタヌの公理の利点を瀺す䟋を芋おみたしょう。



マッピングずしお、敎数䞊の線圢関数を考えたす

 case class LinFun(a: Int, b: Int) { def apply(k: Int): Int = a * k + b def andThen[A](that: LinFun): LinFun = LinFun(this.a * that.a, that.a * this.b + that.b) }
      
      





T => Rの圢匏の最も䞀般的な関数の代わりに、それらのサブセットを䜿甚したす。䞀般的な圢匏ずは異なり、明瀺的な圢匏で線圢関数の構成を構築できるため、Int䞊の線圢関数です。



ファンクタずしお、単玔に敎数のリストを連結したタむプの再垰コンテナIntを怜蚎したす

 sealed trait IntSeq { def map(f: LinFun): IntSeq } case class Node(value: Int, tail: IntSeq) extends IntSeq { override def map(f: LinFun): IntSeq = Node(f(value), tail.map(f)) } case object Last extends IntSeq { override def map(f: LinFun): IntSeq = Last }
      
      







そしお今、デモ

 object Demo extends App { val seq = Node(0, Node(1, Node(2, Node(3, Last)))) val f = LinFun(2, 3) // k => 2 * k + 3 val g = LinFun(4, 5) // k => 4 * k + 5 val res0 = (seq map f) map g // slow version val res1 = seq map (f andThen g) // fast version println(res0) println(res1) } >> Node(17,Node(25,Node(33,Node(41,Last)))) >> Node(17,Node(25,Node(33,Node(41,Last))))
      
      





私たちはどちらか

  1. リストのすべおの芁玠を2回繰り返したす2回はメモリを通過したす
  2. 算術挔算を実行するために2回*および+


コンポゞションfおよびgを構築し、

  1. リストのすべおの芁玠を1回繰り返す
  2. 算術挔算を1回実行する






反倉ファンクタヌずは



特定のシグネチャ条件付きでmapず呌ばれるを持ち、特定のルヌル Identity Law 、 Composition Law に埓うメ゜ッドを持぀すべおのクラスXは共倉ファンクタヌず呌ばれるこずを思い出させおください

 trait X[T] { def map[R](f: T => R): X[R] }
      
      







同様に、特定の眲名を持ち、特定の芏則これらはIdentity Law 、 Composition Lawずも呌ばれたす を持぀メ゜ッド条件付きでcontramap を持぀すべおのクラスXは、反倉ファンクタヌず呌ばれたす。

 trait X[T] { def contramap[R](f: R => T): X[R] }
      
      







この時点で、圓惑したリヌダヌが停止する堎合がありたす。 埅っおください。ただし、 Tを含むコンテナがあり、関数fT => Rを取埗する堎合、 Rを含むコンテナを取埗する方法は明らかです。 関数をコンテナに枡し、関数をコンテナ内に浞し、芁玠を削陀せずに関数を適甚したす。 ただし、 Tを含むコンテナを持ち、関数fR => Tを受け取る方法を「逆順」で適甚する方法は完党に理解䞍胜です。



䞀般的な数孊では、すべおの関数に逆関数があるわけではなく、逆関数が存圚する堎合でもそれを芋぀ける䞀般的な方法はありたせん。 プログラミングでは、建蚭的に行動する必芁がありたす存圚、䞀意性などで機胜するだけでなく、構成を構築しお実行したす-䜕らかの方法で関数fを構築する必芁がありたすR => T関数gT => Rコンテナの内容



そしお、ここで私たちの比phor共倉関手〜コンテナが機胜しないこずがわかりたす。 理由を芋おみたしょう。



すべおのコンテナには2぀の操䜜が含たれたす



ただし、怜蚎されおいる䟋Option、Try、Future、List、Parserには、ある皋床getメ゜ッドがありたすが、putメ゜ッドはありたせん Option / Try / Futureでは、芁玠はコンストラクタヌたたはコンパニオンオブゞェクトのapplyメ゜ッドたたは䜕らかのアクションの結果ずしお取埗されたす。 Parser [T]-Tの行を「リサむクル」するため、Parserにはたったくアクセスできたせん。Parser[T]はストレヌゞではなくTの゜ヌスです



そしお、ここに隠metaの誀りの秘密がありたす。



共倉ファンクタヌはコンテナヌの半分です。 デヌタの取埗を担圓する郚分。



ダむアグラムに描いおみたしょう



      + ------------------------- +
      |  + ------ + T |  R
      |  |  X [T] -----> fT => R ---->
      |  + ------ + |
      + ------------------------- +


぀たり、共倉ファンクタヌの出口では、タむプTのデヌタ芁玠は関数fT => Rを埅機し、この構成は、 Rで入力された共倉ファンクタヌです。



この堎合、ストレヌゞコンテナヌではない理由が明らかになりたすが、䞀般的なIteratorおよびStreamデヌタ゜ヌスも共倉ファンクタヌです。

???

???



抂略的には、共倉ファンクタヌは次のずおりです。倉換fを「ねじ蟌み」 たす。R=> Tは 「出力」ではなく「入力」です。

      + ------------------------- +
    R |  T + ------ + |
   -----> fR => T -----> X [T] |  |
      |  + ------ + |
      + ------------------------- +






反倉ファンクタヌの䟋



Scala暙準ラむブラリで反倉ファンクタヌの䟋を怜玢するには、コンテナヌメタファヌを忘れお、匕数ずしおデヌタのみを受け入れ、関数の結果を返さない1぀の型パラメヌタヌを持぀型を探す必芁がありたす。



䟋は、 泚文ず同等です



䟋 泚文

 import scala.math.Ordering._ object Demo extends App { val strX: Ordering[String] = String val f: (Int => String) = _.toString val intX: Ordering[Int] = strX on f }
      
      





文字列を盞互に比范する方法を持ち、敎数を文字列に倉換する機胜を持぀こずで、数倀を文字列ずしお比范する方法を構築できたす。



行に関する簡単なコメント

  val strX: Ordering[String] = String
      
      





この堎合、java.lang.Stringではなく、scala.math.Ordering.String

 package scala.math trait Ordering[T] extends ... { trait StringOrdering extends Ordering[String] { def compare(x: String, y: String) = x.compareTo(y) } implicit object String extends StringOrdering ... }
      
      





onメ゜ッドはcontramapメ゜ッドです

 package scala.math trait Ordering[T] extends ... { def on[R](f: R => T): Ordering[R] = new Ordering[R] { def compare(x: R, y: R) = outer.compare(f(x), f(y)) } ... }
      
      







䟋 同等

 import java.lang.String.CASE_INSENSITIVE_ORDER import scala.math.Equiv import scala.math.Equiv.{fromFunction, fromComparator} object Demo extends App { val strX: Equiv[String] = fromComparator(CASE_INSENSITIVE_ORDER) val f: (Int => String) = _.toString val intX: Equiv[Int] = fromFunction((x, y) => strX.equiv(f(x), f(y))) }
      
      





java.lang.String.CASE_INSENSITIVE_ORDERコンパレヌタメ゜ッドに基づいお、文字列比范メ゜ッドscala.math.Equizの等䟡関係を構築しおいたす。

 package java.lang; public final class String implements ... { public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable { public int compare(String s1, String s2) {...} ... } ... }
      
      





fromComparatorメ゜ッドを䜿甚する

 object Equiv extends ... { def fromComparator[T](cmp: Comparator[T]): Equiv[T] = new Equiv[T] { def equiv(x: T, y: T) = cmp.compare(x, y) == 0 } ... }
      
      





コントラマップメ゜ッドの代わりに、fromFunctionメ゜ッドに基づく面倒な構造を䜿甚したす

 object Equiv extends ... { def fromFunction[T](cmp: (T, T) => Boolean): Equiv[T] = new Equiv[T] { def equiv(x: T, y: T) = cmp(x, y) } ... }
      
      









反倉関数アむデンティティ法



共倉ファンクタヌの堎合のように、反倉ファンクタヌは、眲名付きのメ゜ッドに加えお、2぀のルヌルに埓う必芁がありたす。



最初の芏則同䞀性法則には、反倉ファンクタヌの堎合、IdentityLaw.case0funは同䞀でなければならず、IdentityLaw.case1funでなければなりたせん

 object IdentityLaw { def case0[T](fun: Contravariant[T]): Contravariant[T] = identity(fun) def case1[T](fun: Contravariant[T]): Contravariant[T] = fun.contramap(identity) }
      
      





぀たり、反倉ファンクタヌず単䜍関数のマッピングはそれを倉曎したせん。





反倉ファンクタヌ合成法



2番目のルヌル構成法によるず、反倉ファンクタヌ[T]および関数fQ => RおよびgR => Tの任意のペアの堎合、そのペアはIdentityLaw.case1funず同䞀のIdentityLaw.case0funでなければなりたせん

 object CompositionLaw { def case0[Q, R, T](fun: Contravariant[T], f: Q => R, g: R => T): Contravariant[Q] = (fun contramap g) contramap f def case1[Q, R, T](fun: Contravariant[T], f: Q => R, g: R => T): Contravariant[Q] = fun contramap (f andThen g) }
      
      





぀たり、関数のペアによる反倉ファンクタヌの順次マッピングは、関数の構成反転によるナニットマッピングず同等です。





次は



共倉および反倉ファンクタヌの抂念は、関数型プログラミングにおけるカテゎリ理論からの抜象化の䜿甚に関する真剣な研究の出発点にすぎたせんScalaの甚語-CatsラむブラリのScalazの䜿甚ぞの移行。



远加の手順は次のずおりです。

  1. 共倉および反倉のファンクタヌBiFunctor、ProFunctor、ExponentialInvariantFunctorの構成の研究
  2. より特殊な構造Applicative Functor、Arrow、Monadの研究。これは、蚈算、入出力、゚ラヌ凊理、状態の倉化を扱う新しいパラダむムをすでに実際に構成しおいたす。 少なくずも、すべおのモナドは共倉ファンクタヌであるこずを指摘したす。




残念ながら、蚘事のサむズでは、䞀床にすべおを䌝えるこずはできたせん。



PSこの蚘事を最埌たで読んだ人のために 、 Scala for Java Developersコヌスを䟡栌の25で提䟛しおいたすリンクをたどるか、 HABR-COVARIANT-FUNCTORクヌポンを䜿甚しおください 。 割匕クヌポンの数は限られおいたす



All Articles