「怖い」Haskellの抜象化。数孊もコヌドもありたせんほが。 パヌトI

-モナドずは䜕ですか

-副䜜甚から玔粋な蚈算を分離するため。

Haskell蚀語に関するオンラむンディスカッションから


シャヌロックホヌムズずワト゜ン博士は気球で飛んでいたす。 濃霧になり、方向を倱いたす。 小さなギャップがありたす-そしお、圌らは地球䞊の人間を芋たす。

-芪愛なる、私たちがどこにいるか教えおもらえたすか

「颚船かごに入れお」

その埌、圌らはそれらをさらに運び、再び圌らは䜕も芋えたせん。

「それは数孊者でした」ずホヌムズは蚀いたす。

「でもなぜ」

-圌の答えは絶察に正確ですが、絶察に圹に立ちたせん。

冗談


叀代゚ゞプト人が5匹の魚を数えたず曞きたいず思ったずき、圌らは5匹の魚の絵を描いた。 圌らが70人を数えたず曞きたいず思ったずき、圌らは70人の人物を描きたした。 圌らが矀れで300匹の矊を数えたず曞いたずき、圌らは...-たあ、䞀般的に、あなたは理解しおいたす。 そのため、叀代゚ゞプト人は、最も知的で怠zyな人々がこれらすべおの蚘録に共通する䜕かを芋るたで苊しみ、数えおいる量の抂念を数えおいるものの性質から分離したした。 そしお、別の賢い怠zyな゚ゞプト人は、人々が数字を指定するために䜿甚しおいた倚くのスティックをはるかに少ない文字数で眮き換え、短い組み合わせで膚倧な数のスティックを眮き換えるこずができたした。



これらの賢い怠zyな゚ゞプト人がしたこずは、抜象化ず呌ばれたす。 圌らは、䜕かの量に関するすべおの蚘録に特城的な共通点に気づき、この共通点をカりントされたオブゞェクトの特定のプロパティから分離したした。 今日の数字ず呌ばれるこの抜象化の意味ず、それが人々の生掻をどれほど楜にしおいるのかを理解しおいれば、Haskell蚀語の抜象化を理解するこずは難しくありたせん。 カテゎリの数孊的理論から私たちに来た恐ろしい名前にもかかわらず、それらを理解するこずは「数字」ず呌ばれる抜象化より難しくありたせん。 それらを理解するために、カテゎリヌの理論、たたは高校のボリュヌムの数孊さえも知る必芁はありたせん算数で十分です。 たた、恐ろしい倚くの数孊的抂念に頌らずに、それらを説明するこずもできたす。 そしお、Haskellの抜象化の意味は数字の意味ずたったく同じです-プログラマヌにずっお生掻が楜になりたすそしおどれだけ想像するこずもできたせん。



機胜プログラムず呜什プログラムの違い

玔粋な機胜の利点を発芋する

蚈算ず「その他」

「他の䜕か」のカプセル化

ファンクタヌは簡単ではありたせんが、非垞に簡単です

適甚ファンクタヌも非垞に簡単です

あなたは笑いたすが、モナドも簡単です

そしお、さらにいく぀かのモナドを定矩したしょう

モナドを適甚する

ラむタヌモナドを定矩し、モノむドを知る

モノむドずファンクタヌ、適甚ファンクタヌおよびモナドの法則

型クラス倚数の機胜が無料で

I / OIOモナド



抜象化を理解および受け入れするには、通垞、人々はそれらをいく぀かの角床から芋る必芁がありたす。



最初に、提案された抜象化の圢匏で耇雑さのレベルを远加するこずで、垞に遭遇する非垞に高いレベルの耇雑さを排陀できるこずを理解する必芁がありたす。 したがっお、玔粋な関数を䜿甚しおプログラマが遭遇するこずのない膚倧な数の問題に぀いお説明したす心配するこずはありたせん。以䞋に説明したす。


第二に、提案された抜象化がどのように実装されたか、そしおこの実装がどのように特定のケヌスではなく非垞に倚様な異なる状況でそれを䜿甚できるかを理解する必芁がありたす。 したがっお、Haskellの抜象化を実装するロゞックを説明し、それらが適甚可胜なだけでなく、信じられないほど倚くの状況で倧きな利点を提䟛するこずを瀺したす。


そしお第䞉に、人々は抜象化がどのように実装されるかだけでなく、それらを日垞生掻にどのように適甚するかを理解する必芁がありたす。 したがっお、これに぀いおは蚘事で説明したす。 さらに、それは単玔ではありたせんが、非垞に単玔です-これらの抜象化がどのように実装されおいるかを理解するよりも簡単ですそしお、説明された抜象化の実装を理解するこずは難しくないこずがわかりたす。


ただし、導入は倚少遅れたため、おそらく開始したす。 蚘事にはコヌドがほずんどないので、その抜象化の矎しさずパワヌを理解しお評䟡するためにHaskellの構文に粟通する必芁はありたせん。



免責事項
私は経隓豊富なHaskellプログラマヌではありたせん。 私はこの蚀語が本圓に奜きで、珟時点ではただ孊習過皋にありたす知識の習埗だけでなく、思考の再構築も必芁なため、これは最速のプロセスではありたせん。 最近、私は関数型プログラミングずHaskellに぀いお、呜什型プログラミング蚀語のみに粟通しおいるプログラマヌず䜕床も話さなければなりたせんでした。 この過皋で、Haskell蚀語の䞻芁な抜象化に぀いお、より明確で構造化された説明に取り組む必芁があるこずに気付きたした。 この資料は、そのような構造化の詊みにすぎたせん。 読者の皆さんが、私のプレれンテヌションの䞍正確な可胜性ず、あなたに十分に理解されおいないように思えた瞬間の䞡方を私に指摘しおいただければ幞いです。


機胜プログラムず呜什プログラムの違い



関数型蚀語ず呜什型蚀語で曞かれたプログラムを鳥瞰図で芋るず、違いはありたせん。 これらのプログラムず他のプログラムはどちらも、゜ヌスデヌタを受け入れ、゜ヌスから倉換された他のデヌタを出力する䞀皮のブラックボックスです。 ブラックボックス内でデヌタ倉換がどのように行われるかを正確に理解するために、ブラックボックス内を確認する堎合に違いを確認したす。



呜什型ブラックボックスを確認するず、それに含たれるデヌタが倉数に割り圓おられ、必芁なデヌタを取埗するたでこれらの倉数が繰り返し倉曎され、ブラックボックスから発行されるこずがわかりたす。



機胜的なブラックボックスでは、着信デヌタの発信デヌタぞのこの倉換は、着信デヌタぞの䟝存の芳点から最終結果が衚される特定の匏を適甚するこずによっお行われたす。 孊校のカリキュラムから、移動の平均速床が䜕に䟝存しおいるか芚えおいたすか そうです移動したパスず移動した時間から。 初期デヌタパスSず時間t 、および平均速床 S / t の蚈算匏がわかれば、最終結果平均速床を蚈算できたす。 最終結果が初期デヌタに䟝存するずいう同じ原理に埓っお、関数スタむルで蚘述されたプログラムの最終結果が蚈算されたす。 同時に、呜什型プログラミングずは異なり、蚈算のプロセスでは、倉数の倉曎はありたせん-ロヌカルでもグロヌバルでもありたせん。



実際、前の段萜では、単語formulaの代わりに単語functionを䜿甚する方が正しいでしょう。 呜什型プログラミング蚀語の関数ずいう蚀葉は、数孊、物理孊、および関数型プログラミング蚀語でこの甚語が意味するものずはたったく呌ばれないこずが倚いため、私はこれをしたせんでした。 呜什型蚀語では、関数はしばしばより正確にプロシヌゞャず呌ばれるもの、぀たり、プログラムサブプログラムの名前付き郚分ず呌ばれ、繰り返し発生するコヌドの繰り返しを回避するために䜿甚されたす。 少し埌に、関数型プログラミング蚀語の関数いわゆるpure関数 、たたはpure関数 が呜什型プログラミング蚀語の関数ずどのように異なるかを理解できたす。



泚プログラミング蚀語の呜什型ず機胜型ぞの分割は、かなりarbitrary意的です。 呜什型ずみなされる蚀語では関数型スタむルで、関数型ずみなされる蚀語では呜什型スタむルでプログラミングできたす Haskellの呜什型スタむルで階乗を蚈算し、Cの同じプログラムず比范するプログラムの䟋です -それは単に䞍䟿です。 したがっお、呜什型プログラミングを奚励する呜什型蚀語ず、関数型プログラミングを奚励する蚀語ずしお機胜型蚀語を考えおみたしょう。



玔粋な機胜の利点を発芋する



Haskellプログラマヌがいわゆる玔粋な関数を扱う時間の倧郚分もちろん、すべおはプログラマヌに䟝存したすが、ここではどのようにすべきかに぀いお話しおいたす。 実際、これらの関数は「玔粋」ず呌ばれるため、呜什型プログラミングで「関数」ずいう甚語が意味するものず混同されたせん。 実際、これらは甚語の数孊的な理解においお最も䞀般的な機胜です。 以䞋に、3぀の数字を远加するこのような関数の最も簡単な䟋を瀺したす。



addThreeNumbers xyz = x + y + z
      
      





Haskell構文に䞍慣れな人のための説明
=蚘号の巊偎の関数の郚分では、関数の名前が垞に最初に来お、次にスペヌスで区切られお、この関数の匕数が行きたす。 この堎合、関数名はaddThreeNumbersであり、 x 、 y、およびzはその匕数です。



=蚘号の右偎には、匕数の芳点から、関数の結果がどのように蚈算されるかが瀺されおいたす。


=蚘号 等号 に泚意しおください。 呜什型プログラミングずは異なり、割り圓お操䜜を意味するものではありたせん。 等号は、圌の巊にあるものが圌の右にある衚珟ず同じであるこずを意味したす。 数孊のように 6 + 4は10 ず同じなので、 6 + 4 = 10ず曞きたす。 どの蚈算でも、10の代わりに匏6 + 4を眮き換えるこずができ、10を眮き換えた堎合ず同じ結果が埗られたす。 Haskellの同じこず addThreeNumbers xyz



代わりに、匏x + y + z



眮き換えるこずができ、同じ結果が埗られたす。 ずころで、コンパむラはたさにそれを行いたす-関数名に遭遇するず、代わりにその本䜓で定矩された匏を眮き換えたす。



この機胜の「玔床」ずは䜕ですか



関数の結果は、匕数のみに䟝存したす。 同じ匕数でこの関数を䜕床呌び出しおも、関数は倖郚状態を参照しないため、垞に同じ結果を返したす。 圌女は倖の䞖界から完党に隔離されおおり、蚈算では、私たちが圌女の議論ずしお明瀺的に䌝えたものだけを考慮しおいたす。 歎史などの科孊ずは異なり、数孊的蚈算の結果は、共産党が暩力を握っおいるか、民䞻党員か、プヌチン倧統領かによっお巊右されたせん。 私たちの関数は数孊に由来したす-それは枡された匕数にのみ䟝存し、それ以䞊には䟝存したせん。



自分で確認できたす。この関数の匕数ずしお倀1、2、4を䜕回枡しおも、垞に7になりたす。「3」の代わりに「2 + 1」を枡すこずもできたす。 「4」-「2 * 2」。 これらの匕数で別の結果を取埗するオプションはありたせん。


addThreeNumbers



関数は、倖郚状態に䟝存しないだけでなく、倉曎もできないため、玔粋ずaddThreeNumbers



呌ばれたす。 圌女は匕数ずしお枡されたロヌカル倉数を倉曎するこずさえできたせん。 圌女ができるそしおすべきこずは、圌女に枡された匕数の倀に基づいお結果を蚈算するこずです。 ぀たり、この機胜には副䜜甚はありたせん。


これにより䜕が埗られたすか なぜHaskellistsは、ロヌカルおよびグロヌバル倉数の倉異に基づいお構築された呜什型プログラミング蚀語の䌝統的な機胜を芋お、このような軜pur的な方法でその機胜の「玔床」を保持するのでしょうか。



玔粋な関数の蚈算結果は倖郚状態にたったく䟝存せず、倖郚状態を倉曎しないため、共通のリ゜ヌスをめぐっお競合するデヌタの競合を心配するこずなく、これらの関数を䞊列に蚈算できたす。 副䜜甚は䞊列蚈算の死であり、私たちの玔粋な関数にはそれらがないため、心配する必芁はありたせん。 関数を蚈算する順序や、蚈算を䞊列化する方法を気にせずに、玔粋な関数を蚘述するだけです。 Haskellで蚘述しおいるからこそ、すぐに䞊列化できたす。


さらに、玔粋な関数を同じ匕数で耇数回呌び出すため、垞に同じ結果が埗られるこずが保蚌されおいるため、Haskellは䞀床蚈算された結果を蚘憶し、同じ匕数で関数が再床呌び出されるず、再床評䟡せずに以前に蚈算された結果を眮き換えたす。 これはメモ化ず呌ばれたす。 これは非垞に匷力な最適化ツヌルです。 結果が垞に同じであるこずがわかっおいるのに、なぜ再びカりントするのでしょうか


呜什型プログラミングの本質が厳密に定矩されたシヌケンス内の倉数の突然倉異倉曎にある堎合、関数型プログラミングの本質はデヌタの䞍倉性ず関数の構成にありたす。



関数g :: a -> b



「型aの匕数を取り、型bの倀を返す関数g」ず読むず関数f :: b -> c



がある堎合、それらを合成するこずで関数h :: a -> c



取埗できたすh :: a -> c



。 タむプaの倀を関数gの入力に䟛絊するこずにより、出力でタむプbの倀を取埗したす-関数fはたさにこのタむプの入力を受け取りたす。 したがっお、関数gの蚈算結果を関数fにすぐに転送できたす。その結果は、タむプcの倀になりたす。 次のように曞かれおいたす。



 h :: a -> c h = f . g
      
      









関数fずgの間のポむントは、次のタむプの合成挔算子です。



 (.) :: (b -> c) -> (a -> b) -> (a -> c)
      
      





合成挔算子は、通垞の関数ず同じ方法括匧内で括匧内で䜿甚されるため、ここでは括匧で囲たれおいたす。 2぀の匕数の間で䞭眮スタむルで䜿甚する堎合、括匧なしで䜿甚されたす。



合成挔算子は、関数fに察応する最初の匕数ずしお関数b -> c



を取りたす矢印は型-関数の型も瀺したす。 2番目の匕数、圌は関数も受け取りたす-ただし、タむプa -> b



、これは関数gに察応したす。 そしお、構成挔算子は、関数h :: a -> c



a -> c



に察応するa- a -> c



型の新しい関数をusに返したす。 機胜矢印には右結合性があるため、最埌の括匧を省略できたす。



 (.) :: (b -> c) -> (a -> b) -> a -> c
      
      





ここで、構成挔算子は、 b -> c



およびb -> c



a -> b



型の2぀の関数ず、2番目の関数の入力に転送されるa型の匕数を枡す必芁があるこずがわかりたす。出力では、 c



型の倀を取埗したす。機胜。

構成挔算子がドットで瀺される理由
数孊では、 f ∘ g



ずいう衚蚘は、関数の構成を瀺すために䜿甚されたす。これは、「f after g」を意味したす。 ポむントはこのシンボルに䌌おいるため、構成挔算子ずしお遞択されたした。


機胜の構成f . g



f . g



はf (gx)



ず同じ意味-぀たり 関数g



を匕数x



適甚した結果に適甚される関数f







ちょっず埅っお そしお、関数h = fの定矩で倱われたタむプaの匕数はどこにありたしたか。 g 合成挔算子ぞの匕数ずしお2぀の関数が衚瀺されたすが、g関数ぞの入力に枡される倀は衚瀺されたせん
同じ匕数が関数定矩の「=」蚘号の巊ず右の最埌の堎所にあり、この匕数が他のどこでも䜿甚されおいない堎合、省略できたすただし、垞に䞡偎から。 数孊では、匕数は「関数の適甚ポむント」ず呌ばれるため、この蚘述スタむルは「無意味」ず呌ばれたす通垞、合成挔算子のようなポむントの蚘録では、倚数ありたす:)。


関数の合成が関数型プログラミング蚀語の本質であるのはなぜですか はい、関数型蚀語で曞かれたプログラムは関数の合成に過ぎないためです 関数は、プログラムの構成芁玠です。 それらを構成するず、他の関数を取埗し、独自の方法で、新しい関数を取埗するように構成したす-など。 デヌタはある関数から別の関数に流れ、倉換し、関数を構成するための唯䞀の条件は、ある関数によっお返されるデヌタが次の関数が取るものず同じ型を持぀こずです。



Haskellの関数はクリヌンであり、明瀺的に枡された匕数にのみ䟝存しおいるため、関数構成チェヌンからある皮の「ブリック」を簡単に「匕き出し」お、リファクタリングたたは完党に眮き換えるこずさえできたす。 泚意する必芁があるのは、新しいブリック関数が叀いブリック関数ず同じ型の入力倀ず出力倀で受け入れるこずだけです。 それだけです 玔粋な関数は倖郚状態に䟝存しないため、関数に関係なく関数をテストできたす。 プログラム党䜓をテストする代わりに、個々の機胜をテストしたす。 私たちの堎合、この非垞に重芁な話で説明されおいる状況は、単に䞍可胜になりたす。



マヌケティング担圓者はプログラマヌに次のこずを尋ねたす。

-倧芏暡プロゞェクトをサポヌトする難しさは䜕ですか

「たあ、あなたが䜜家であり、戊争ず平和プロゞェクトをサポヌトしおいるず想像しおください」ずプログラマヌは答えたす。 -あなたはTKを持っおいたす-ナタヌシャ・ロストワが雚の䞭で公園を歩いた方法に぀いおの章を曞きたす。 「雚が降っおいた」ず曞いお保存するず、「ナタヌシャ・ロストノァが亡くなりたした。続行できたせん」ずいう゚ラヌメッセヌゞが衚瀺されたす。 どうしお死んだのどうしお死んだの あなたは理解し始めたす。 ピ゚ヌル・ベズホフの぀る぀るした靎、圌が萜ち、銃が地面にぶ぀かり、ポストからの匟䞞がナタヌシャに跳ね返ったこずがわかりたした。 どうする 銃をアむドル状態に充電したすか 靎を亀換したすか 柱を取り倖すこずにしたした。 削陀しお保存し、「Rzhevskyäž­euが死亡したした。」ずいうメッセヌゞを受け取りたす。 もう䞀床、あなたは座っお理解し、次の章で圌はもはやポヌルに傟いおいるこずがわかりたす...


Haskellistsが玔粋な機胜をそれほど重芖しおいる理由を理解しおください。 第䞀に、デヌタ競合を心配するこずなく、努力なしで䞊列化されたコヌドを曞くこずができたす。 次に、コンパむラヌが蚈算を効率的に最適化できるようにしたす。 そしお第䞉に、副䜜甚がなく、玔粋な関数が倖郚状態から独立しおいるため、プログラマは非垞に倧きなプロゞェクトでも簡単にサポヌト、テスト、リファクタリングできたす。



蚀い換えれば、Haskell蚀語の䜜成者は、䞖界の倖郚状態から完党に隔離された䞖界、぀たりすべおの機胜がきれいで、状態がなく、すべおが䞍可胜に最適化されおおり、すべおが努力なしで䞊列化された䞖界の倖郚状態から完党に隔離された䞖界を思い付きたした偎。 蚀語ではなく、倢 Eugenio Moggi がモナドの抂念に関する科孊的研究でリストした「些现な事」をどうするかを理解するこずだけが残っおいたす。



真空のこの非垞に球圢の銬で、私たちが隔離されおいる倖の䞖界からだけ来るプログラムの初期デヌタを取埗するにはどうすればよいのでしょうか もちろん、ナヌザヌ入力の結果を玔粋な関数たずえば、キヌボヌドからの文字入力を受け付けるgetChar



関数の匕数ずしお䜿甚できたすが、たず、この方法で、居心地の良いクリヌンな䞖界に必芁な「ダヌティ」関数を䜜成したす。それはそこで䞭断し、次に、そのような関数は垞に同じ匕数 getChar



関数を持ちたすが、ナヌザヌここでは埅ち䌏せが垞に異なるキヌを抌すため、蚈算倀は垞に異なりたす。


プログラムの結果である、居心地の良い、玔粋に機胜的な䞖界から隔離された、倖の䞖界に結果を䞎える方法は 結局、数孊的な意味での関数は垞に結果を返す必芁があり、䞀郚のデヌタを倖郚に送信する関数は䜕も返さないため、関数ではありたせん


いわゆる郚分的に定矩された関数、぀たり、すべおの匕数に察しお定矩されおいない関数をどうしたすか たずえば、よく知られおいる陀算関数はれロによる陀算に察しお定矩されおいたせん。 このような関数は、甚語の数孊的な意味での本栌的な関数でもありたせん。 もちろん、そのような匕数に察しお䟋倖をスロヌできたすが、...


...しかし、䟋倖はどうしたすか 䟋倖は、玔粋な関数から期埅される結果ではありたせん


非決定的コンピュヌティングをどうするか ぀たり、正しい蚈算結果が1぀ではなく、倚くの堎合です。 たずえば、単語の翻蚳を取埗したい堎合、プログラムはその意味のいく぀かを䞀床に瀺し、それぞれが正しい結果になりたす。 玔粋な関数は垞に1぀の結果のみを返す必芁がありたす。


そしお、続線をどうするか 継続ずは、いく぀かの蚈算を実行した埌、それらが完了するのを埅たずに珟圚の状態を保存し、他のタスクに切り替えるこずです。そのため、完了埌に䞍完党な蚈算に戻り、䞭断したずころから続行したす。 状態がなく、ありえない玔粋に機胜的な䞖界では、どのような状態に぀いお話しおいるのでしょうか


そしお、最埌に、どういうわけか倖郚状態を考慮するだけでなく、䜕らかの方法でそれを倉曎する必芁がある堎合、䜕をすべきでしょうか


蚈算をクリヌンに保ち、衚明された問題を解決する方法を䞀緒に考えたしょう。 そしお、これらすべおの問題に察しお共通の解決策が芋぀かるかどうかを芋おみたしょう。



蚈算ず「その他」



そのため、玔粋な機胜に粟通し、その玔粋さがプログラマが盎面する最も耇雑な問題を取り陀くこずができるこずに気付きたした。 しかし、玔粋な機胜を掻甚する胜力を維持するために解決しなければならない倚くの問題に぀いおも説明したした。 私はそれらを再び䞎えたすI / Oに関連する問題を取り陀きたすが、これに぀いおは埌で説明したす、それらの䞀般的なパタヌンを芋るこずができるようにそれらをいくらか再線成したす



すべおの匕数に察しお定矩されおいない関数がある堎合がありたす。 関数が定矩されおいるこの関数に匕数を枡すずき、結果を蚈算する必芁がありたす。 しかし、定矩されおいない匕数を枡す堎合、関数が䜕か他のもの 䟋倖、゚ラヌメッセヌゞ、たたは呜什型null



類䌌物を返すようにしたす 。


関数が結果を1぀ではなく、他の䜕か たずえば、結果のリスト党䜓、たたはたったく結果なし結果の空のリストを䞎えるこずがありたす。


関数の倀を蚈算するために、匕数だけでなく、 䜕か他のもの たずえば、倖郚環境からのデヌタ、構成ファむルからの蚭定なども取埗したい堎合がありたす。


次の関数を枡すために蚈算の結果を取埗するだけでなく、 それを他の䜕かに匕数ずしお適甚したい堎合もありたす䜕らかの状態を取埗した埌、戻っお蚈算を続行するこずができたす。これは継続の意味です。


蚈算を実行するだけでなく、 䜕か他のこずも実行したい堎合がありたす たずえば、ログに䜕かを曞き蟌む。


関数を䜜成するずきに、蚈算の結果だけでなく、 他の䜕か たずえば、最初にどこかから読み取り、次に䜕らかの方法で制埡された方法で倉曎するなどを次の関数に枡したい堎合がありたす 。


䞀般的なパタヌンに気づきたしたか 擬䌌コヌドでは、次のように蚘述できたす。



  ( /  - ) { //    / //  -  return (   / - ) }
      
      







もちろん、この「他の䜕か」を関数の远加匕数ずしお枡すこずができたすこのアプロヌチは呜什型プログラミングで䜿甚され、「スレッド状態」ず呌ばれたすが、玔粋な蚈算ず「他の䜕か」䞀床に積み重ねるこずは最良のアむデアではありたせん。 たた、これにより、説明したすべおの状況に察しお単䞀の゜リュヌションを取埗するこずはできたせん。



初めに議論され、数字を発明した叀代゚ゞプト人を思い出したしょう。 倚くの矊の図を描く代わりに、圌らは蚈算をその文脈から分離したした 。 珟代的には、コンピュヌティングずそのコンテキストをカプセル化したした。 そしお、それらの前に量を蚈算する抂念が私たちが考えおいるこずず密接に関連しおいる堎合、圌らの革新はそれを2぀の䞊行する「実行フロヌ」に分割したした-蚈算に盎接接続されたストリヌムずそれは -぀たり、蚈算のコンテキストです蚈算䞭にコンテキストを保存できるだけでなく、たずえば矀れの矊から䜕匹のケバブが埗られるかを蚈算するず、コンテキストも倉曎されるためです。







Haskellで「他の䜕か」を衚珟し、同時に最も䞀般化された゜リュヌションを取埗したい堎合、この「他の䜕か」を远加のタむプずしお衚珟したす。 ただし、単玔型ではなく、他の型を匕数ずしお取る関数型です。 耇雑で分かりにくいですね。 心配しないでください、それは非垞に簡単で、数分埌にあなた自身で芋るでしょう。



「他の䜕か」のカプセル化



1998幎12月11日、火星を研究するために火星気候オヌビタヌ宇宙船が打ち䞊げられたした。 デバむスが火星に到達した埌、それは倱われたした。 調査埌、制埡プログラムでは、䞀郚の距離がむンチ単䜍で考慮され、他の距離はメヌトル単䜍で考慮されるこずが刀明したした。 どちらの堎合も、これらの倀はDouble



型で衚されおいたした。 関数がむンチ単䜍でカりントした結果、メヌトル単䜍で衚された匕数が枡されたため、圓然、蚈算で゚ラヌが発生したした。



このような゚ラヌを回避したい堎合は、メヌトルで衚された倀がむンチで衚​​された倀ず異なる必芁がありたす。したがっお、間違った単䜍で衚された倀を関数に枡そうずするず、コンパむラヌが゚ラヌを通知したす。 Haskellでは、これは非垞に簡単です。 2぀の新しい型を宣蚀したしょう。



 data DistanceInMeters = Meter Double data DistanceInInches = Inch Double
      
      







DistanceInMeters



ずDistanceInInches



はタむプコンストラクタヌず呌ばれ、 Meter



ずInch



はデヌタコンストラクタヌず呌ばれたすタむプコンストラクタヌずデヌタコンストラクタヌは異なるスコヌプに存圚するため、同じようにするこずができたす。



これらの型宣蚀を芋おください。 デヌタコンストラクタヌは関数のように動䜜し、匕数ずしおDouble



型の倀を取り、蚈算の結果ずしおDistanceInMeters



型たたはDistanceInInches



型の倀を返すず思いたせんか そうです-デヌタコンストラクタヌも関数です そしお、以前に誀っおDouble



型の倀をDouble



を取る関数に枡すこずができた堎合、この関数では、匕数にDouble



型の倀だけでなく、 䜕か他のもの 、぀たり- «» Meter



Inch



.



ただし、この堎合、最も䞀般的な゜リュヌションは埗られたせんでした。圓瀟の機胜konstruktory_dannyhの匕数Meter



ずInch



の型の倀のみを取るこずができたすDouble



。これは、この特定のタスクのロゞックによっお決定されたすが、メむンタスクを解決するために-玔粋なコンピュヌティングを「他の䜕か」から分離したす-この「他の䜕か」を衚珟する「ラッパヌ」が圌らの匕数を取るこずができる必芁がありたすタむプ。たた、このタスクはHaskellで非垞に簡単に解決できたす。Haskell組み蟌みタむプの1぀を芋おください。



 data Maybe a = Nothing | Just a
      
      





ここに曞かれおいるこずを理解しおいない人のための説明
, Maybe



, a



. « » , — Double



, Bool



, DistanceInMeters



, . , Maybe a



2 — Nothing



Just



( a



). «»: Nothing



, Just



- (, Just True



) — Maybe a



( Just



True



, Maybe Bool



).


芋お、Maybe



どんなタむプの倀でも取るこずができるラッパヌがありたす。このラッパヌには、䜕らかの倀を含めるこずができたすデヌタコンストラクタヌを䜿甚する堎合Just



か、䜕も含めるこずはできたせんデヌタコンストラクタヌを䜿甚する堎合Nothing



。ラッパヌ内にデヌタがあるかどうかを確認するには、ラッパヌMaybe



を怜査するだけです。マッチ箱のようなものです。箱が空かどうかを確認するために、箱を開ける必芁はありたせん。箱を耳に持っおきお振るだけです。Haskellは、



型Maybe



を䜿甚しお問題の1぀を解決したす。すべおの匕数に察しお定矩されおいない玔粋な関数をどう凊理するかです。たずえば、関数がありたすlookup



、キヌずペアの連想リストキヌ、倀を枡しお、このキヌに関連付けられた倀を芋぀けるこずができたす。ただし、この関数は、枡されたキヌずのペアを芋぀けられない堎合がありたす。この堎合、それは私たちNothing



に返され、それが芋぀かった堎合、にラップされた倀を私たちに返しJust



たす。぀たり関数に定矩された倀を枡すず、蚈算の結果をラッパヌでJust



取埗し、定矩されおいない倀を枡すず、「䜕か他のもの」Nothing



を取埗したす。



しかしNothing



、だけでなく、関数が蚈算の結果ではなく「他の䜕か」を返した理由に関するメッセヌゞも取埗したい堎合はどうでしょうか。問題をより明確に定矩したしょう蚈算が成功した堎合、結果が返された堎合、および倱敗した堎合は、゚ラヌメッセヌゞ、蚈算の結果、゚ラヌメッセヌゞはさたざたなタむプになりたす。 OK、このように曞きたしょう



 data Either ab = Left a | Right b
      
      





型コンストラクタEither



は、型の2぀の倉数を受け入れるこずがわかりたす- a



およびb



異なる型でも、同じ型でもかたいたせん。蚈算の結果が成功した堎合、それらをラッパヌで取埗しRight



蚈算の結果はtypeになりたすb



、蚈算が倱敗した堎合、デヌタコンストラクタヌのラッパヌでaの゚ラヌを取埗したすLeft



。



さお、倖郚環境での䜜業はどうですか蚈算の倀が䜕らかの倖郚環境に䟝存しおいる堎合は、必芁な倀を蚈算する関数に読み蟌んで匕数ずしお枡す必芁がありたすか述べたように、そしお曞いおください



 data Reader ea = Reader (e -> a)
      
      





蚈算結果が䟝存する環境は型倉数で瀺されe



型倉数の代わりに必芁な型に眮き換えるこずができるこずを思い出しおください、蚈算結果の型は型倉数で瀺されたすa



。さらに、蚈算自䜓にはtypeがe -> a



ありたす。環境から必芁な䟡倀ぞの機胜です。



同じこずが、単䞀の結果たたは他の䜕かれロの結果たたは倚くの結果を返す可胜性のある非決定的蚈算にも圓おはたりたす。これらを远加の型でラップしたす。そしお、あなたはおそらく知っおいるこのタむプ-リストのこのタむプ[a]



のように曞くこずができたす。この「他の䜕か」を衚し、倉数の型-圓瀟の玔蚈算のタむプ。[] a



[]



a







玔粋な蚈算の実行ず䞊行しお倉曎する必芁がある状態であろうず、プログラムの実行䞭に発生する可胜性がある䟋倖であろうず、「他の䜕か」に぀いおも同じこずを行いたす。私たちは、私たちで「ラップ」たちの玔粋な蚈算のクラスでは、この「䜕かを」、カプセル化し、「他の䜕か」の凊理ず2぀の䞊列ストリヌム䞊のネットの蚈算を共有し、私たちが取り組んでいる、それぞれが明確に。



この時点で孊んだこずをたずめお芁玄したしょう。



玔粋な関数を䜿甚するこずにより、蚈算の䞊列化、コンパむラによる蚈算の最適化、非垞に倧きなプログラムでもテスト、サポヌト、リファクタリングの容易さに関連する倧きな利点を埗るこずができたす。


, , , «- ». , , «- », «- ».


«- », . «- » .


«- » «» , «» .


:



 a -> mb
      
      





m



— « », b



.


, . , - :



a -> b



, .. . ma



. ma -> mb



, , «» a -> b



m



, a -> b



, mb



.


, , first class citizens. ぀たり , — , .. , , , «» m



. f



, a



, , mf



ma



, « »:



 mf ` ` ma => m (f ` ` a).
      
      





, , , , , , . f :: b -> c



g :: a -> b



, f . g



, g



, f



. f :: b -> mc



g :: a -> mb



? mb



b



— , , b



«» m



.



«» b



m



次の関数の倀ずしお枡すため。実際、玔粋な蚈算ず䞊行しお、「ラッパヌ」には「他の䜕か」の蚈算があり、この蚈算の結果を次の関数に枡す必芁もありたす。䞀般的に、我々は機胜をkompozirovatできる方法を把握する必芁があるa -> mb



ずb -> mc



私たちはそこから新しい機胜を埗るこずができるこずa -> mc



、およびこの組成物は、我々は、「他の䜕か」のない蚈算をネット蚈算を倱っおいないしおいないずき。さらに、おそらく既に掚枬されおいるように、私たちの゜リュヌションも普遍的でなければなりたせん。




ファンクタヌは簡単ではありたせんが、非垞に簡単です



したがっお、3぀のタスクがありたす。



ラップされた倀に通垞の倀で機胜する既存の関数をどのように適甚できるかを理解するため。


, , , .


, , — , , , «- », .


原則ずしお、funktsionalschikiは怠惰な人ではなかった堎合、圌らは考えimperativschikamiされおいるだけで包たれたデヌタを操䜜するための新機胜の束を曞きたした。isChar :: a -> Bool



枡された倀が型の倀Char



であるかどうかをチェックする関数の類䌌物を決定するには、ラッパヌ型のデヌタコンストラクタヌず同じ数の方皋匏を蚘述する必芁がありたす。たずえば、ラッパヌタむプMaybe a



には2぀のデヌタコンストラクタヌがJust



ありNothing



たす。



 maybeIsChar :: Maybe Char -> Maybe Char -> Maybe Bool maybeIsChar (Just x) = Just (isChar x) maybeIsChar Nothing = Nothing
      
      





そのため、わざわざこれは芋た目ではありたすがせずに、ラップされたデヌタを操䜜するための各玔粋関数の類䌌物を定矩できたす。そしお、関数ごずにだけでなく、ラッパヌごずに察応するアナログを蚘述する必芁がありたす



しかし、それは別の方法で行うこずができたす。既に持っおいる玔粋な関数を最初の匕数ずしお受け取り、それをラッパヌに含たれる倀に適甚する新しい関数を定矩しお、同じラッパヌにラップされた新しい倀を返すこずができたす。この関数を呌び出したすfmap







 fmap :: (a -> b) -> ma -> mb
      
      





これで、ラッパヌタむプごずに通垞の関数の䜕癟もの類䌌物を定矩する代わりに、ラッパヌタむプごずに関数を1぀だけ定矩できたすfmap



。fmap



ラッパヌタむプの関数を定矩したしょうMaybe a







 fmap f (Just x) = Just (fx) fmap _ Nothing = Nothing
      
      





そしお、2番目の匏のfmap関数の最初の匕数の代わりにこの䞋線は䜕ですか
fmap



a -> b



. , , , , . - , . , .


これで、ラップされた型の倀にMaybe a



型関数を適甚できたすa -> b



。関数fmap



を1぀だけ定矩するこずで、倚くの远加䜜業をなくすこずに同意したす。同じフレヌズの発音は異なる堎合がありたす。ラッパヌ型をMaybe a



ファンクタヌにしたため、倚くの远加䜜業がなくなりたした。



はい、はいラッパヌ型をファンクタヌにするには、関数を定矩する必芁がありたすfmap



。これにより、通垞の倀で機胜する関数をラッパヌに「泚入」できたす。ファンクタヌは非垞にシンプルだず蚀いたした䟿利です これにより、以前に定矩された玔粋な関数を通垞だけでなく、ラップされた倀でも䜿甚できたす。



適甚ファンクタヌも非垞に簡単です



ラップされおいない倀で機胜する関数をラップされた倀に適甚する方法を芋぀けたした。しかし、関数自䜓もラップされおいる堎合はどうでしょうかラップされた倀にどのように適甚したすか



掚枬したず思いたす。ラップされた関数を最初の匕数ずしお、ラップされた倀を2番目の匕数ずしおずる関数を宣蚀し、そのような操䜜が必芁なラッパヌタむプごずにこの関数を定矩する必芁がありたす。この関数を呌び出したす<*>



read apply; 関数の名前が​​小文字ではなく特殊文字で始たるずいう事実は、䞭眮圢匏で䜿甚する必芁があるこずを瀺しおいたす。通垞の関数のように接頭蟞圢匏で䜿甚する堎合は、括匧で囲む必芁がありたす



 (<*>) :: m (a -> b) -> ma -> mb
      
      





typeに察しお宣蚀された関数を定矩したしょうMaybe a



。同時に、この型には2぀のコンストラクタヌがあるこずを思い出しおください。぀たり、この型でラップされた関数ずラップされた倀はJust



たたはNothing



のいずれかです。



 (Just f) <*> Nothing = Nothing Nothing <*> _ = Nothing (Just f) <*> (Just x) = Just (fx)
      
      





これで、最初は通垞の倀でしか動䜜しなかったラップされた関数をラップされた倀に適甚できたすラッパヌがtypeである堎合Maybe



。他のラッパヌでも同じこずができるようにしたい堎合、必芁なのはそれらのそれぞれに察しお関数を定矩するこず(<*>)



です。蚀い換えるず、これらのラッパヌをアプリカティブファンクタにする必芁がありたす。関数(<*>)



ずが定矩されおいるラッパヌタむプはアプリカティブファンクタであるためですpure



。



関数pure



は䜕をしたすかああ、ファンクタヌや応甚ファンクタヌよりも簡単ですこの関数pure



は通垞の倀を取り、それからラップされた倀を䜜成したす。圌女のタむプは次のずおりです。



 pure :: a -> ma
      
      





pure



ラッパヌ型の関数を定矩Maybe



しお、実際の適甚可胜なファンクタヌにしたす。



 pure x = Just x
      
      





すべおが非垞に耇雑ですよね碑文「Sarcasm」のプレヌト



ずころで、ラッパヌ型を適甚可胜なファンクタヌにするこずで、察応する数のラップされた匕数に任意の数の通垞の匕数を取る関数を適甚できたすファンクタヌは、1぀の匕数の通垞の関数のみをラップされた倀に適甚できたす。これは、䟋えば、我々が远加できるか、であるJust 2



ずJust 3







 pure (+) <*> Just 2 <*> Just 3 > Just 5
      
      





コヌドは完党に明確ではありたせんか
pure Maybe



(+)



, . 2 (<*>)



.


この構文は奜きではありたせんかこれを詊しおください
, , . liftAN



, A Applicative (functor), N , , . (+), :



 liftA2 (+) (Just 3) (Just 2) > Just 5
      
      





, : ( | a + b | )







 ( | (Just 3) + (Just 2) | ) > Just 5
      
      









あなたは笑いたすが、モナドも簡単です



そこで、1぀の匕数の通垞の関数をラップされた倀に適甚する方法を芋぀けたした。これを行うには、ラッパヌタむプの関数を定矩する必芁がありたすfmap



。そしお、この関数をラッパヌタむプに実装したため、ファンクタヌになるために必芁なものは䜕もないため、誇らしげにファンクタヌず呌ばれる暩利がありたす。



たた、ラップされた倀にラップされた関数を適甚する方法を芋぀けたした。これを行うには、ラッパヌタむプに2぀の関数を定矩する必芁がありたす- pure



そしお<*>



-たた、これにより、任意の数の匕数を取るラップされた倀に通垞の関数を適甚できたした。そしお、これらの関数をラッパヌタむプに定矩するずすぐに、アプリケヌションファンクタず呌ばれる暩利を獲埗したした。ずころで、ラッパヌ型を適甚可胜なファンクタヌにするためには、最初に通垞のファンクタヌにする必芁がありたすそしお、チヌトするこずはできたせん-コンパむラヌはこれに埓いたす。これには論理的なそしお、い぀ものように、簡単な説明がありたす。この蚘事はすでに非垞に膚れ䞊がっおいるので、あなた自身で勉匷するために残しおおきたす。



それは、我々は2぀の機胜の構図を䜜るこずができる方法を理解するために私たちのために残っおいるa -> mb



、ずb -> mc



そのため、玔粋な蚈算の結果ず、ラッパヌに含たれる「他の䜕か」を蚈算した結果の䞡方が、最初の関数から2番目の関数に転送されたす。おそらく既に掚枬されおいるように、このためには、ラッパヌタむプに察しお1぀たたは2぀の関数を定矩する必芁がありたす。そしお、最も独創的な人は、これらの関数が定矩されるラッパヌ型がモナドず呌ばれるこずをすでに理解しおいたす。



これらの関数の最初は関数return



です。return



関数からの出口点を定矩するこずは必須ではありたせん。 Haskell関数return



は通垞の倀を取り、それからラップされた倀を䜜成したす。



 return :: a -> ma
      
      





pure



ラッパヌ型を適甚可胜なファンクタヌに倉えた章の関数のように聞こえたすか぀たり、これらの関数は同じ仕事をしたす。そしお、モナドを䜜成したいラッパヌ型は、最初に適甚可胜なファンクタヌそしおその前に-単なるファンクタヌにならなければならないずいうルヌルがありたす。぀たり、このラッパヌ型に察しお、すでに玔粋関数return



を定矩しおいるので、関数を非垞に定矩できたすシンプル



 return = pure
      
      





ラッパヌ型をモナドにするために定矩する必芁がある2番目の関数が呌び出されたす(>>=)



読み取りバむンド。次のタむプがありたす。



 (>>=) :: mb -> (b -> mc) -> mc
      
      





うヌん...それは実際に機胜の構成に䌌おいない䜕か。そうです。関数(>>=)



はラップされた倀ずtype の関数を受け取り、a -> mb



タむプラッパヌでラップされた玔粋な蚈算の結果ず「䜕か」を蚈算した結果たたはこれを保存した結果の䞡方をこの関数に枡す方法を決定する必芁がありたすラッパヌ自䜓に含たれる「蚈算」が行われなかった堎合は「その他」。぀たりこの堎合、関数を衚瀺せずa -> mb



、その結果ずしお型の倀を取埗したしたmb



。぀たり、すでにどこかにあるずいうこずです。ただし、この関数を䜿甚しお、構成関数を少し埌で定矩したす(>>=)



。それたでの間、それをしおください。ラッパヌのtypeを



実装(>>=)



したしょうMaybe



。圌には2぀のデヌタコンストラクタヌがあるため、これには2぀の方皋匏が必芁です。「arrow to Leysley」ずいう名前から、b -> mc



文字のような関数を呌び出したしょう通垞の倀を取り、ラップされた倀を返す関数はすべお「Claysley Arrows」ず呌ばれ、以前に実装した関数も「Claysley Arrow」ですk



return







 —       Nothing,   Nothing Nothing >>= _ = Nothing —       ,    ""    k (Just x) >>= k = kx
      
      





以䞊です。ラッパヌ型Maybe



はモナドになりたしたこれをするためにしなければならなかったこずは、機胜return



ずそれを決定するこず(>>=)



でした。



玔粋な機胜を提䟛し、保持した利点に加えおそれは私たちに䜕を䞎えたしたか意味を䌝えたいクラむズリヌの矢印のコンベダヌ党䜓を想像しおください。これらの各Claysley矢印はMaybe



、デヌタコンストラクタヌを䜿甚しおラッパヌにラップされた倀Just



、たたはNothing



。明らかに、このチェヌンからのある皮のKleisley矢印がを䞎えたNothing



堎合、この倀をパむプラむンに沿っおさらに枡すこずは意味がありたせん。それで、私たちは䜕をしたすか各矢印の操䜜埌、クレむズリヌは助けを借りおチェックしif then else



、前の関数を返したせんでしたNothing



か



皇垝はたさにそれを行い、倚くのネストされた構造からstructuresい構造を構築したすif then else



。しかし、(>>=)



このような錫なしでこの問題を解決する関数を定矩したした。自分で確認しおくださいどこかNothing



に珟れた堎合、挔算子は(>>=)



関数に枡さずにパむプラむンの最埌たで単玔に「ストレッチ」したす。したがっお、nullの チェックを心配するこずなく、蚈算チェヌンを䜜成できたすNothing



。モナドを䜿甚するず、玔粋な関数を䜿甚する利点を維持できるだけでなく、コヌドをはるかに少なく蚘述でき、コヌド自䜓がはるかに読みやすくなりたす。



そしお、さらにいく぀かのモナドを定矩したしょう



もう1぀のモナドを定矩したしょうか型Either ab



よりも゚ラヌず䟋倖をより明確に凊理できるラッパヌ型を䜿甚したすMaybe



。このタむプの定矩を思い出しおみたしょう。



 data Either ab = Left a | Right b
      
      





-このタむプは2぀のコンストラクタ、のいずれかを持っおいるLeft



-入力するように蚭定されおいるa



-これは我々がラッパヌである゚ラヌメッセヌゞに䜿甚するこずのタむプは、このように「他の䜕か」されおいる、第二は、 - Right



-タむプに蚭定されおいたすb



-これが「基本的な」蚈算のタむプです。 「基本的な」蚈算が過剰に行われない堎合、蚈算の倀はClaysley矢印の構成のチェヌンに沿っおデヌタコンストラクタヌでラップされRight



たす。そしお、゚ラヌが発生するずすぐに-デヌタコンストラクタヌを䜿甚しおラップされた結果のメッセヌゞを取埗したすLeft



。



最初に関数を定矩したすreturn







 return x = Right x
      
      





ここではすべおが明らかです。return



゚ラヌメッセヌゞを関数に枡すのではなく、䜕らかの型の倀b



を枡すため、デヌタコンストラクタ関数をこの倀に適甚しRight



お型の倀を取埗したすEither ab



。



ここで、挔算子を定矩したす(>>=)



。ここでのロゞックはモナドず同じMaybe



ですチェヌンに沿っおタむプ倀が枡される少なくずも1぀のKleisley矢印Either ab



が、デヌタコンストラクタヌ関数Left



でラップされた゚ラヌメッセヌゞを衚瀺する堎合、蚈算チェヌン党䜓の結果はこの゚ラヌメッセヌゞになりたす。すべおの蚈算が成功した堎合぀たり、各Claysley矢印がdata_constructor関数を䜿甚しおラップされた蚈算の結果を返した堎合Right



、次の各機胜をこの結果に適甚する必芁がありたす。



 (Left x) >>= _ = Left x (Right x) >>= k = kx
      
      





モナドMaybe



などEither



。どちらにも2぀のデヌタコンストラクタヌがあり、そのうちの1぀は蚈算の倱敗を瀺したすしたがっお、次の関数に枡さずに、クレむズリヌの矢印でコンポゞションの最埌に「ドラッグ」する必芁がありたす。䞡方のモナドの2番目のデヌタコンストラクタヌは、蚈算が正垞に完了したこずを意味し、これらの蚈算の倀は次のKleisley矢印に枡されたす。



それでは、以前に実装されたモナドずは異なるモナド、リストモナドを実装したしょう。リストモナドのClaysley矢印のタむプはa -> [b]



です。挔算子の最初の匕数(>>=)



はラップされた型の倀ですma



。この堎合、これは[a]



型の倀のリストa



です。さらに、リストは空の堎合もあれば、タむプの1぀以䞊の倀を含む堎合もありたすa



。



この堎合、Claysley矢印を倀のリストに適甚するずはどういう意味ですかこれは、リストの各倀に適甚する必芁があるこずを意味したす。空のリストの堎合、すべおが明確です。Claysley矢印を䜿甚するものは䜕もないので、結果ずしお空のリストを取埗したす。空でないリストの各倀に察しお、関数を䜿甚しおClaysley矢印を適甚できたすfmap



リストからモナドを䜜成するため、これはリストがファンクタヌでもあるこずを意味したす-芚えおいたすか。ただし、functionのタむプを思い出しおみたしょう。fmap



䟿宜䞊、抜象ラッパヌタむプm



を特定のラッパヌリストタむプに眮き換えたす。



 fmap :: (a -> b) -> [a] -> [b]
      
      





次に、枡されfmap



た関数のタむプをClaysley矢印のタむプに眮き換えたす。



 fmap :: (a -> [b]) -> [a] -> [[b]]
      
      





Kleisley矢印を枡した結果fmap



、type mb



ではなくtypeの倀を取埗するこずがわかりたすmmb



。二重にラップしたす。これはoperatorのタむプに察応しない(>>=)



ため、ラッパヌの1぀を「削陀」する必芁がありたす。これを行うにconcat



は、リストのリストを受け入れ、内郚リストを連結し、通垞の倀のリストを返す関数がありたす。これで(>>=)



リストモナドの挔算子を定矩する準備ができたした



 [] >>= _ = [] xs >>= k = (concat . fmap k) xs
      
      





挔算子を決定するロゞックは(>>=)



、すべおの堎合で同じであるこずがわかりたす。ラップされた各倀には、蚈算の結果ず「他の䜕か」があり、別の関数に枡すずきに蚈算ずこの「他の䜕か」で䜕をする必芁があるかを考えたす。 「その他」は、蚈算の成功たたは倱敗のマヌカヌ、蚈算の成功たたぱラヌメッセヌゞのマヌカヌ、蚈算がれロから無限の結果を返すこずができるマヌカヌの堎合がありたす。 「他の䜕か」はログ゚ントリ、぀たり読み取り、「基本」蚈算の匕数ずしお枡す状態にするこずができたす。たたは、「基本」蚈算ず䞊行しお、読み取り、倉曎、および別の関数に枡された状態を再床倉曎したす。



モナドには耇雑なものは䜕もないこずを認めなければなりたせんファンクタヌや応甚ファンクタヌのように。モナドは、2぀の関数が定矩されおいる単なるラッパヌタむプです- return



ず(>>=)



。



ただし、(>>=)



ステヌトフルラッパヌの定矩はやや耇雑です。それらの実装には、この蚘事で玹介したものよりもHaskellの構文に粟通しおいる必芁があるため、ここでは玹介したせん。しかし、私はあなたを安心させたいです。第䞀に、非垞に高床なHaskellプログラマヌでさえ、通垞はモナドを䜜成せず、組み蟌み蚀語を䜿甚したす。これは、あらゆる堎合に十分です。第二に、モナド状態で動䜜するものを含むを䜿甚するこずは、モナドを定矩するよりもはるかに簡単です。これに぀いおは、次の章で説明したす。



モナドを理解するには、単玔な原則を理解する必芁がありたす。「基本的な」蚈算ず、䞊行しお発生する「他の䜕か」の蚈算がありたす。たた、「クレむズリヌシュヌタヌ」の「コンベア」でこれらの蚈算がどの皋床正確に行われるかは、オペレヌタヌが決定し(>>=)



たす。したがっお、挔算子を自分(>>=)



で定矩する必芁はほずんどありたせんが、そこに䜕がどのように発生するかをよりよく理解するために、さたざたな組み蟌みモナド型に察しお定矩される方法を理解するこずは非垞に圹立ちたす。



ちなみに、挔算子(>>=)



がクレむズリヌの矢印の合成の切り捚おられたバヌゞョンであるず蚀ったずき、私はそれを通しお実際の合成を決定するこずを玄束したした。これはHaskell蚀語の暙準関数であり、ず衚瀺され(>=>)



、「魚」「魚挔算子」ず発音されたす。



 (>=>) :: (a -> mb) -> (b -> mc) -> a -> mc (f >=> g) x = fx >>= g
      
      





x



私たちが持っおいるタむプはvalue a



でf



あり、g



Kleisleyの矢印です。 Claysley矢印f



をvalue x



に適甚するず、ラップされた倀が取埗されたす。そしお、芚えおいるように、ラップされた倀をClaysleyの次の矢印に転送する方法は、オペレヌタヌが知っおい(>>=)



たす。



次のパヌトでは、Haskell蚀語で定矩されたモナドを䜿甚する方法を芋おいきたすそしお、倧倚数のプログラマヌは他のモナドを必芁ずしたせん。Writer



ログ゚ントリの「他の䜕か」で衚珟されおいる、モノむドずは䜕か、なぜモノむドが必芁なのかを説明する正圓な理由がありたす。そしお、「タむプクラス」ず呌ばれるもう1぀の匷力なHaskellメカニズムに぀いお説明し、すでにお䌚いしたファンクタヌ、応甚ファンクタヌ、モナドが、モノむドやタむプクラスずどのように結び付いおいるかを説明しお、話を終わりたす。ただ䌝えおいたせん。そしお最埌に、私は玄束を果たし、通垞のモナドずは異なるI / Oモナドに぀いお簡単に話したすただし、実装のみが異なり、䜿甚䞭は他のモナドず同じくらい簡単です。



All Articles