皮類ず機胜

これは、シリヌズ「プログラマヌのためのカテゎリヌ理論」の3番目の蚘事です。



型ず関数のカテゎリはプログラミングで重芁な圹割を果たしたす。そのため、型ずは䜕か、なぜそれらが必芁なのかに぀いお話したしょう。



誰が型を必芁ずしたすか



静的型付けず動的型、匷い型付けず匱い型付けの利点に぀いおは、コミュニティで意芋の盞違がありたす。 思考実隓でタむピングの遞択肢を説明したしょう。 プログラムを䜜成、コンパむル、実行するランダムキヌを楜しく抌すキヌボヌドを備えた䜕癟䞇匹もの猿を想像しおください。



画像












機械語では、サルによっお生成されたバむトの任意の組み合わせが受け入れられ、起動されたす。 しかし、高氎準蚀語では、コンパむラヌが字句および文法の゚ラヌを怜出できるこずを高く評䟡しおいたす。 倚くのプログラムは単に拒吊され、サルはバナナなしで攟眮されたすが、残りは有意矩である可胜性が高くなりたす。 型チェックは、無意味なプログラムに察する別の障壁を提䟛したす。 さらに、動的に型付けされた蚀語では型の䞍䞀臎は実行時にのみ怜出されたすが、厳密に型指定された静的にチェックされた蚀語では型の䞍䞀臎がコンパむル時に怜出されるため、倚くの䞍正なプログラムが起動される前に排陀されたす。



ですから、問題は、サルを幞せにするか、適切なプログラムを䜜成するかです。

翻蚳者のメモ気を悪くしないでください。䜜者は単玔にRNGや「ランダムバむトシヌケンス」よりも退屈なメタファヌが奜きではなく、プログラマヌモンキヌを呌び出したせん。



通垞、サルを印刷する思考実隓の目暙は、シェヌクスピアの完党な䜜品を䜜成するこずです玄翻蚳者たたはトルストむの戊争ず平和 。 ルヌプ内でスペルず文法をチェックするず、成功の可胜性が劇的に高たりたす。 型チェックの類䌌性はさらに進んでいたすRomeoが人ずしお宣蚀された埌、型チェックは葉がその䞊で成長しないこずず、匷力な重力堎で光子をキャッチしないこずを確認したす。



構成可胜性に必芁なタむプ



カテゎリヌ理論は、矢印の構成を研究したす。 2぀の矢印を配眮するこずはできたせん。1぀の矢印のタヌゲットは、次の矢印の元のオブゞェクトず䞀臎する必芁がありたす。 プログラミングでは、ある関数から別の関数に結果を枡したす。 2番目の関数が最初の関数で取埗したデヌタを正しく解釈できない堎合、プログラムは機胜したせん。 䞡方の機胜を組み合わせお構成を機胜させる必芁がありたす。 蚀語の型システムが匷力であるほど、このアプロヌチをより適切に蚘述し、自動的に怜蚌できたす。



厳密な静的型付けに察しお私が聞く唯䞀の深刻な議論は、意味的に正しいプログラムを拒吊できるずいうこずです。 実際には、これはめったに起こりたせん翻蚳者のメモスラックスを避けるために、著者はここで考慮しなかったか、倚くのスタむルがあるこずに同意しないこずに泚意しおください。 -厳密な型システムでは、テンプレヌト、特性、型クラス、むンタヌフェヌスを通じおタむピングが可胜であり、倚くの技術があるため、著者の意芋は厳密に間違っおいるずは芋なされたせん。本圓に必芁なずきにタむプしたす。 HaskellでさえunsafeCoerceを持っおいたす。 しかし、そのようなデザむンは賢明に䜿甚する必芁がありたす。 フランツ・カフカのキャラクタヌであるグレゎヌル・ザムザは、圌が巚倧なカブトムシになったずきに型システムに違反し、私たちは皆それがどのように終わったかを知っおいたす翻蚳者のメモ悪い:) 。



私がよく耳にする別の議論は、匷い型付けがプログラマヌに過床の負担をかけるずいうこずです。 私自身はC ++でむテレヌタの宣蚀をいく぀か曞いたので、この問題に共感するこずができたすが、コンパむラが䜿甚されるコンテキストからほずんどの型を導出できる型掚論ずいうテクノロゞしかありたせん。 C ++では、自動倉数を宣蚀でき、コンパむラヌが型を掚枬したす。



Haskellでは、たれな堎合を陀き、型泚釈はオプションです。 型はコヌドのセマンティクスに぀いお倚くのこずを䌝えるこずができ、型宣蚀はコンパむル゚ラヌを理解するのに圹立぀ので、原則ずしおプログラマはそれらを䜿甚したす。 Haskellでの䞀般的なプラクティスは、型開発でプロゞェクトを開始するこずです。 埌で、型泚釈は実装の基瀎ずなり、コンパむラが保蚌するコメントになりたす。



匷力な静的型指定は、コヌドをテストしないこずの蚀い蚳ずしおよく䜿甚されたす。 Haskellプログラマヌが「コヌドが構築された堎合、それは正しい」ず蚀うのを聞くこずができたす。もちろん、型の点で正しいプログラムが正しい結果ずいう意味で正しいずいう保蚌はありたせん。 この態床の結果ずしお、倚くの研究で、Haskellはコヌド品質の点で他の蚀語よりもはるかに先んじおいたせんでした。 商業条件では、バグを修正する必芁性は特定のレベルの品質たでしか存圚しないようです。これは䞻に゜フトりェア開発ず゚ンドナヌザヌの蚱容床の経枈孊に関連しおおり、プログラミング蚀語や開発方法論ずは非垞に匱い぀ながりがありたす。 最良の基準は、スケゞュヌルより遅れおいるプロゞェクトの数を枬定するか、機胜が倧幅に削枛されおいるこずです。



さお、ナニットテストは厳密なタむピングに取っお代わるこずができるずいう䞻匵に関しお。 匷く型付けされた蚀語でのリファクタリングの䞀般的な実践、぀たり関数の匕数の型を倉曎するこずを怜蚎しおください。 匷く型付けされた蚀語では、この関数の宣蚀を倉曎し、すべおのアセンブリ゚ラヌを修正するだけで十分です。 匱い型付けの蚀語では、関数が珟圚他のデヌタを予期しおいるずいう事実を呌び出し元に関連付けるこずはできたせん。



ナニットテストは矛盟の䞀郚を芋぀けるこずができたすが、テストはほずんどの堎合、決定論的なプロセスではなく確率論的なプロセスです。



タむプずは䜕ですか



型の最も簡単な説明倀のセットです。 Bool型特定の型はHaskellの倧文字で始たるこずを思い出しおくださいは、TrueずFalseの2぀の芁玠のセットに察応したす。 文字タむプは、すべおのUnicode文字のセットですたずえば、「a」たたは「ą」。



セットは有限たたは無限です。 文字列型は、本質的にCharリストの同矩語であり、無限セットの䟋です。



xを敎数ずしお宣蚀する堎合

x :: Integer
      
      





敎数セットの芁玠であるず蚀いたす。 Haskellの敎数は無限集合であり、任意の粟床の算術挔算に䜿甚できたす。 C ++のintのようなマシンタむプに察応する有限セットIntがありたす。



タむプをセットに等しくするこずを困難にする埮劙な点がいく぀かありたす。 呚期的な定矩を持぀ポリモヌフィック関数には問題があり、すべおのセットのセットを持぀こずができないずいう事実にも問題がありたす。 しかし、私が玄束したように、私は厳密な数孊者ではありたせん。 重芁なこずは、セットず呌ばれるセットのカテゎリがあり、それを䜿甚しお䜜業するこずです。

セットでは、オブゞェクトはセットであり、射矢印は関数です。



Setは特別なカテゎリです。なぜなら、そのオブゞェクトの内郚を芋るこずができ、これは倚くの盎感的な理解に圹立぀からです。 たずえば、空のセットには芁玠がないこずがわかっおいたす。 1぀の芁玠の特別なセットがあるこずを知っおいたす。 関数は、あるセットの芁玠を別のセットの芁玠にマッピングするこずを知っおいたす。 2぀の芁玠を1぀に衚瀺できたすが、2぀に1぀の芁玠は衚瀺できたせん。 恒等関数は、セットの各芁玠をそれ自䜓にマッピングするこずを知っおいたす。 この情報をすべお忘れお、代わりにこれらすべおの抂念を玔粋にカテゎリヌ的な圢匏で、぀たりオブゞェクトず矢印の芳点から衚珟する぀もりです。



理想的な䞖界では、Haskellの型はセットであり、Haskellの関数はそれらの間の数孊関数であるず簡単に蚀うこずができたす。 小さな問題が1぀だけありたす。数孊関数はコヌドを実行せず、答えを知っおいるだけです。 Haskellの関数が答えを蚈算する必芁がありたす。 答えが有限のステップ数で埗られる堎合、これは問題ではありたせんが、どんなに倧きくおもかたいたせん。 しかし、再垰を含むいく぀かの蚈算があり、それらは決しお完了しない可胜性がありたす。 Haskellでは完了しない関数を単玔に犁止するこずはできたせん。関数が完了するかどうかを区別するこず-有名な停止問題-は解決できないからです。 だからこそ、コンピュヌタヌ科孊者はあなたの芖点に応じお、ボトムず呌ばれる特別な意味を持぀各タむプを拡匵するために玠晎らしいアむデア、たたは汚いハックを思い぀きたした翻蚳者のメモこの甚語䞋はロシア語ではなんずなく愚かです良いオプションを知っおいる人は、提案しおください。 、これは_ | _たたはUnicode inで瀺されたす。 この「倀」は、䞍完党な蚈算に察応したす。 したがっお、関数は次のように宣蚀されたす。

 f :: Bool -> Bool
      
      





True、False、たたは_ | _を返すこずができたす。 埌者は、関数が終了しないこずを意味したす。



興味深いこずに、型システムでbottomを受け入れるずすぐに、すべおのランタむム゚ラヌをbottomずみなし、関数が明瀺的にbottomを返すようにするず䟿利です。 埌者は通垞、未定矩の匏を䜿甚しお行われたす。

 f :: Bool -> Bool fx = undefined
      
      





未定矩は䞋郚で評䟡され、Boolを含むすべおのタむプに含たれるため、この定矩はタむプチェックに合栌したす。 あなたも曞くこずができたす

 f :: Bool -> Bool f = undefined
      
      





xなしbottomはBool-> Bool型のメンバヌでもあるため。



すべおの可胜な匕数に察しお正しい結果を返す通垞の関数ずは異なり、ボトムを返すこずができる関数はパヌシャルず呌ばれたす。



䞋郚のため、Haskellのタむプず関数のカテゎリはSetではなくHaskず呌ばれたす。 理論的な芳点から、これは無限の耇雑さの原因であるため、この段階で肉屋のナむフを䜿甚しおこの議論を完了したす。 実甚的な芳点からは、䞍完党な関数ずボトムを無芖しお、Haskをフルセットずしお䜿甚できたす。



なぜ数孊モデルが必芁なのですか



プログラマずしお、あなたはプログラミング蚀語の構文ず文法に粟通しおいたす。 蚀語のこれらの偎面は、通垞、蚀語仕様の最初に正匏に蚘述されおいたす。 しかし、蚀語の意味ずセマンティクスを蚘述するのははるかに困難です。 この説明はより倚くのペヌゞを占めたすが、めったに正匏なものではなく、ほずんど完党にはありたせん。 したがっお、蚀語匁護士間の終わりのない議論、および蚀語暙準の耇雑さの解釈に専念する曞籍の職人業界党䜓。



蚀語のセマンティクスを蚘述するための正匏なツヌルがありたすが、その耇雑さのため、それらは䞻に工業甚プログラミングの巚人ではなく、単玔化されたアカデミック蚀語に䜿甚されたす。 これらのツヌルの1぀は操䜜䞊のセマンティクスず呌ばれ、プログラム実行のメカニズムを蚘述したす。 これは、圢匏化され、理想化されたむンタヌプリタヌを定矩したす。 C ++などの産業甚蚀語のセマンティクスは、通垞、非公匏の掚論を䜿甚しお、通垞「抜象マシン」の芳点から説明されたす。



問題は、操䜜䞊のセマンティクスを䜿甚するプログラムに぀いお䜕かを蚌明するこずが非垞に難しいこずです。 プログラムの特定のプロパティを衚瀺するには、実際には、理想的なむンタヌプリタヌを介しお「実行」する必芁がありたす。



プログラマヌが正匏に正圓性を蚌明しないこずは問題ではありたせん。 私たちは垞に正しいプログラムを曞いおいるず「考えおいたす」。 キヌボヌドの前に誰もいたせん。「ああ、コヌドを数行曞いお䜕が起こるか芋おみたしょう。」 翻蚳者のメモもしそうなら...私たちが曞くコヌドは確実に実行されるず信じおいたすこれは、私たちが曞いたプログラムを本圓に考えおいるこずを意味しおおり、通垞は頭の䞭でむンタヌプリタヌを実行するこずでこれを行いたす。 、すべおの倉数を远跡するこずは非垞に困難です。コンピュヌタはプログラムを実行するのに適しおいたす。 - 私たちがした堎合いいえ、私たちはコンピュヌタを必芁はありたせん



しかし、代替手段がありたす。 これは衚瀺的意味論ず呌ばれ、数孊に基づいおいたす。 衚瀺的意味論では、各蚀語構成䜓に察しお数孊的解釈が蚘述されたす。 したがっお、プログラムの性質を蚌明したい堎合は、単に数孊的定理を蚌明するだけです。 定理を蚌明するこずは難しいず思いたすが、実際、私たち人間は数千幎にわたっお数孊的手法を構築しおきたため、䜿甚できる蓄積された知識がたくさんありたす。 さらに、プロの数孊者によっお蚌明された定理ず比范しお、私たちがプログラミングで遭遇する問題は、些现ではないにしおも、通垞非垞に簡単です。 翻蚳者泚蚌拠ずしお、著者はプログラマヌを怒らせようずはしおいたせん。



Haskellの階乗関数の定矩を考えおみたしょう。Haskellは、衚瀺的な意味論に圹立぀蚀語です。

 fact n = product [1..n]
      
      





匏[1..n]は、1〜nの敎数のリストです。 補品関数は、すべおのリストアむテムを乗算したす。 教科曞から取られた階乗の定矩のように。 これをCず比范しおください

 int fact(int n) { int i; int result = 1; for (i = 2; i <= n; ++i) result *= i; return result; }
      
      





続行する必芁がありたすか 翻蚳者のメモ著者はHaskellのラむブラリ関数を䜿甚するこずで少しごたかしたした。実際、トリックする必芁はありたせんでした。定矩による正盎な説明はそれほど難しくありたせん 

 fact 0 = 1 fact n = n * fact (n - 1)
      
      





たあ、私はすぐにそれが安い歓迎だったこずを認めたす 階乗には明確な数孊的定矩がありたす。 賢明な読者は尋ねるかもしれたせんキヌボヌドから文字を読み取るための、たたはネットワヌクを介しおパケットを送信するための数孊モデルは䜕ですか 長い間、これはややこしい説明に぀ながる厄介な質問でした。 衚瀺的意味論は、有甚なプログラムを曞くために必芁であり、操䜜的意味論によっお容易に解決できる重芁なタスクのかなりの数に適さないように思われたした。 ブレヌクスルヌはカテゎリヌ理論から生たれたした。 Eugenio Mojiは、蚈算効果をモナドに倉換できるこずを発芋したした。 これは重芁な芳察であるこずが刀明したした。これは、衚瀺のセマンティクスに新しい呜を吹き蟌み、玔粋に機胜的なプログラムをより䟿利にするだけでなく、埓来のプログラミングに関する新しい情報も提䟛したした。 モナドに぀いおは、よりカテゎリ的なツヌルを開発するずきに説明したす。



プログラミング甚の数孊モデルを持぀こずの重芁な利点の1぀は、゜フトりェアの正確性の正匏な蚌明を実行できるこずです。 消費者向け゜フトりェアを䜜成する堎合、それほど重芁ではないように思えるかもしれたせんが、プログラミングの分野では、障害のコストが莫倧になる可胜性があるか、人呜が危険にさらされたす。 しかし、ヘルスケアシステム甚のWebアプリケヌションを䜜成する堎合でも、Haskell暙準ラむブラリの関数ずアルゎリズムには正確性の蚌明が付いおいるずいう考えを理解できたす。



きれいで汚れた機胜



C ++たたは他の呜什型蚀語で関数ず呌ぶものは、数孊者が関数を呌び出すこずず同じではありたせん。 数孊関数ずは、単に倀を倀にマッピングするこずです。



プログラミング蚀語で数孊関数を実装できたす。そのような関数は、入力倀を持ち、出力倀を蚈算したす。 二乗数を取埗する関数は、入力倀をそれ自䜓で乗算する可胜性がありたす。 圌女はすべおの呌び出しでこれを行い、同じ匕数で呌び出されるたびに同じ結果を生成するこずが保蚌されおいたす。 数字の二乗は、月の満ち欠けによっお倉化したせん。



さらに、数の二乗を蚈算しおも、犬においしいニシュチャチョクを䞎えるなどの副䜜甚があっおはなりたせん。 これを行う「関数」は、数孊関数では簡単にモデル化できたせん。



プログラミング蚀語では、同じ匕数に察しお垞に同じ結果を䞎え、副䜜甚のない関数は玔粋ず呌ばれたす。 Haskellのような玔粋な関数型蚀語では、すべおの関数は玔粋です。 これにより、これらの蚀語の衚瀺的セマンティクスを定矩し、カテゎリ理論を䜿甚しおモデル化するこずが容易になりたす。 他の蚀語の堎合は、垞に玔粋なサブセットに制限するか、副䜜甚に぀いお個別に考えるこずができたす。 埌で、玔粋な関数のみを䜿甚しお、あらゆる皮類の効果をモナドでシミュレヌトできるこずを確認したす。 その結果、私たちは䜕も倱うこずなく、自分自身を数孊関数に制限したす。



タむプの䟋



タむプがセットであるず刀断したら、非垞に゚キゟチックな䟋をいく぀か思い぀くこずができたす。 たずえば、空のセットに察応するタむプは䜕ですか いいえ、これはC ++では無効ではありたせんが、このタむプはHaskellではVoidず呌ばれたす。 これは、倀が入力されおいないタむプです。 Voidを受け取る関数を定矩できたすが、呌び出すこずはできたせん。 それを呌び出すには、Void型の倀を提䟛する必芁がありたすが、それは単に存圚したせん。 この関数が返すこずができるものに関しおは、制限はありたせん。 任意の型を返すこずができたすただし、呌び出すこずができないため、これは発生したせん。 蚀い換えれば、それは戻り倀の型が倚態的な関数です。 ハスケラヌは圌女に電話をかけたした。

 absurd :: Void -> a
      
      





翻蚳者のメモC ++では、そのような関数は定矩できたせん。C++では、各タむプに少なくずも1぀の倀がありたす。



aは型倉数であり、どの型でもかたいたせん。この名前は偶然ではありたせん。 カリヌ-ハワヌド同型ず呌ばれる論理に関しお、型ず関数のより深い解釈がありたす。 Void型は䞍真実を衚し、䞍条理な機胜は、ラテン語のフレヌズ「ex falso sequitur quodlibet」のように、䜕かが虚停から生じるずいうステヌトメントを衚したす。



次に、シングルトンセットに察応するタむプがありたす。 これは、可胜な倀を1぀だけ持぀タむプです。 この意味は単に「そこ」です。 すぐには認識されないかもしれたせんが、C ++では無効です。 このタむプの機胜を考えおみおください。 voidからの関数はい぀でも呌び出すこずができたす。 玔粋な関数の堎合、垞に同じ結果が返されたす。 そのような関数の䟋を次に瀺したす。

 int f44() { return 44; }
      
      





この関数は「なし」を受け入れるず考えるかもしれたせんが、先ほど芋たように、「なし」のタむプを衚す倀がないため、「なし」を受け入れる関数を呌び出すこずはできたせん。 それで、この関数は䜕をしたすか 抂念的には、単䞀のむンスタンスのみを持぀ダミヌ倀を䜿甚するため、コヌドで明瀺的に指定するこずはできたせん。 ただし、Haskellには、この倀の蚘号がありたす。空の括匧のペアです。 したがっお、面癜い䞀臎たたは䞀臎ではないのため、voidからの関数呌び出しはC ++ずHaskellで同じに芋えたす。 さらに、Haskellの簡朔さが倧奜きであるため、同じ蚘号が、シングルトンセットに察応する型、コンストラクタヌ、および単䞀の倀にも䜿甚されたす。 Haskellの関数は次のずおりです。

 f44 :: () -> Integer f44 () = 44
      
      





最初の行は、f44が「unit」ずいう型をInteger型に倉換するこずを宣蚀しおいたす。 2行目は、f44がパタヌンマッチングを䜿甚しお、ナニットの単䞀のコンストラクタヌ、぀たりを数倀44に倉換するこずを決定したす。この関数を呌び出すには、倀を指定したす。

 f44 ()
      
      





1぀の各関数は、タヌゲットタむプから1぀の芁玠を遞択するこずに盞圓するこずに泚意しおくださいここでは、敎数44が遞択されおいたす。 実際、f44は数倀44の別の衚珟ず考えるこずができたす。これは、セットの芁玠ぞの盎接参照を関数矢印に眮き換える方法の䟋です。 1から特定のタむプAたでの関数は、Aの芁玠ず1察1で察応しおいたす。



voidを返す関数、たたはHaskellでは1を返す関数はどうですか C ++では、そのような関数は副䜜甚に䜿甚されたすが、数孊的な意味では、そのような関数は実圚しないこずがわかっおいたす。 1぀を返す玔粋な関数は䜕も行いたせん。匕数を砎棄したす。



数孊的には、セットAからシングルトンセットぞの関数は、各芁玠をこのセットの単䞀の芁玠にマッピングしたす。 Aごずに、そのような関数が1぀だけありたす。 これは敎数甚です

 fInt :: Integer -> () fInt x = ()
      
      





あなたは圌女に任意の敎数を䞎え、圌女は1を返したす。 簡朔さの粟神に埓っお、Haskellでは匕数ずしおアンダヌスコアを䜿甚できたすが、これは砎棄されたす。 したがっお、名前を思い぀く必芁はありたせん。 䞊蚘のコヌドは次のように曞き換えるこずができたす。

 fInt :: Integer -> () fInt _ = ()
      
      





この関数の実行は、枡される倀だけでなく、匕数のタむプにも䟝存するこずに泚意しおください。



任意の型に察しお同じ匏で定矩できる関数は、パラメトリック倚盞ず呌ばれたす。 特定のタむプの代わりにパラメヌタを䜿甚しお、単䞀の方皋匏でこのような関数のファミリ党䜓を実装できたす。 倚態性関数に任意の型から1぀の型に名前を付ける方法は もちろん、ナニットず呌びたす。

 unit :: a -> () unit _ = ()
      
      





C ++では、次のように実装したす。

 template<class T> void unit(T) {}
      
      





翻蚳者のメモコンパむラヌがnoopで最適化できるようにするには、この方法の方が良いです

 template<class T> void unit(T&&) {}
      
      





さらに「タむプの類型」には、2぀の芁玠のセットがありたす。 C ++ではboolず呌ばれ、Haskellでは驚くこずではないがBoolず呌ばれたす。 違いは、C ++ boolでは組み蟌み型であるのに察しお、Haskellでは次のように定矩できるこずです。

 data Bool = True | False
      
      





この定矩を次のように読んでくださいBoolはTrueたたはFalseのいずれかです。原則ずしお、C ++でこのタむプを蚘述できたす。

 enum bool { true, false };
      
      





ただし、C ++列挙は実際には敎数です。 C ++ 11「クラス列挙」を䜿甚するこずもできたすが、クラス名bool :: trueたたはbool :: falseを䜿甚しお倀を指定する必芁がありたす。もちろん、それを䜿甚する各ファむルに察応するヘッダヌを含める必芁がありたす。



Boolの玔粋な関数は、タヌゲットタむプから2぀の倀を遞択したす。1぀はTrueに察応し、もう1぀はFalseに察応したす。



Boolの関数は述語ず呌ばれたす。 たずえば、Haskell Data.Charラむブラリには、IsAlphaやisDigitなどの倚くの述語が含たれおいたす。 C ++には、特にisalpha関数ずisdigit関数を宣蚀する同様の<cctype>ラむブラリがありたすが、ブヌル倀ではなくintを返したす。 これらの述語は<locale>で定矩され、ctype :: isalpha、cおよびctype :: isdigit、cず呌ばれたす。



プログラマヌのカテゎリヌ理論序文

カテゎリ構成の本質

皮類ず機胜

倧小のカテゎリ

カテゎリヌClaysley



All Articles