重複の可能性:
モナドとは?
プログラミング以外の用語でモナドをどのように説明しますか? プログラミングの外側 (FP だけでなく、すべてのプログラミングの外側) に、重要な意味で作用する、またはモナドのようであると言える概念/ものはありますか?
重複の可能性:
モナドとは?
プログラミング以外の用語でモナドをどのように説明しますか? プログラミングの外側 (FP だけでなく、すべてのプログラミングの外側) に、重要な意味で作用する、またはモナドのようであると言える概念/ものはありますか?
はい、モナドのようなものと言えるプログラミング外のものがいくつかあります。いいえ、モナドを理解するのに役立つものはありません。抽象化、直観、そして「モナド チュートリアルの誤謬」を読んでください</a>:
Joe Haskeller はモナドについて学ぼうとしています。例を見て、コードを書き、他の人が書いたものを読んで、一週間それらを理解するのに苦労した後、彼はついに「あはは!」を持っています。瞬間: すべてが突然明確になり、Joe はモナドを理解しました! もちろん、実際に起こったことは、ジョーの脳がすべての詳細をより高いレベルの抽象化、つまりジョーがモナドを直感的に把握するために使用できる比喩にまとめたということです。ジョーの比喩が、モナドはブリトーのようなものであると仮定しましょう。ここで、ジョーは自分の思考プロセスをひどく誤解しています。「もちろん!」ジョーは思う。「今はすべてがとてもシンプルです。モナドを理解する鍵は、モナドがブリトーに似ているということです。前から考えていたら!」もちろん、問題は、ジョーが以前にこれを考えていた場合、役に立たなかっただろうということです。
しかし今、Joe は「Monads are Burritos」というモナドのチュートリアルを書いています。これは、他の人が彼の魔法のような洞察を読めば、モナドについて簡単に学べるという善意ではあるが誤った仮定の下で行われます。「モナドは簡単です」と Joe は書いています。「それらをブリトーと考えてください。」Joe は、型などに関する実際の詳細をすべて非表示にしています。それらは怖いからです。人々は、そのような難しくて紛らわしいことをすべて避けることができれば、よりよく学ぶことができます。もちろん、正反対のことが当てはまり、Joe が行ったのは、人々がモナドについて学ぶのを難しくしたことだけです。なぜなら、今では 1 週間かけてモナドはブリトーだと考えて完全に混乱し、その後 1 週間は忘れようとしているからです。彼らが実際にモナドについて学ぶ仕事に取りかかる前に、ブリトーのアナロジーについて。
ずいぶん前に別の回答で言ったように、sigfpe の記事You Could Have Invented Monads! (And Maybe You Already Have.)と、Philip Wadler の元の論文Monads for function programmingはどちらも優れた入門書です (類推ではなく、多くの例を示しています)。些細なこと。
[本当の答えではない: モナドがすべてのプログラミングの外に存在する場所の 1 つは、もちろん数学です。この陽気な投稿が指摘しているように、「モナドはエンドファンクターのカテゴリーのモノイドです。何が問題なのですか?」:-)]
編集:質問者は、「モナドは非常に複雑で、類推を超えている」などと言って、この回答を見下したものと解釈したようです。実際、そのようなことは意図されていませんでした。「モナドを理解する必要はない」と言い直したほうがいいかもしれません。特定のモナドは便利だから使う — Maybe 型が必要なときは Maybe モナドを使い、IO が必要なときは IO モナドを使う。、Nullable<> パターン、LINQ、クエリ内包表記などを使用します。ここで、モナドと呼ばれるこれらすべての構造の根底にある単一の一般的な抽象化があるという洞察は、特定のモナドを理解または使用するために必要ではありません。これは、複数の例を見てパターンを認識した後、後付けとして考えられるものです。つまり、学習は具体的なものから抽象的なものへと進みます。抽象化自体のアナロジーに訴えることによって抽象化を直接説明することは、通常、学習者が抽象化が何であるかを理解するのに役立ちません。
ここに私の現在の刺し傷があります:
モナドはバケットブリゲードです:
>>=
、操作を介して)。return
バケツに物を入れる操作です。>>
) 操作の場合、バケットの内容は次の人に渡される前にダンプされます。次の人はバケツに何が入っていたかは気にせず、受け取るのを待っているだけです。()
、バケット内でチケットが渡されます。それは「ザ・ユニット」と呼ばれ、ただの白紙です。お役に立てれば。:-)
編集:サポートに感謝しますが、悲しいことに、モナド チュートリアルの呪いが再び襲いました。私が説明したのは、モナドではなく、コンテナーを使用した単なる関数アプリケーションです! しかし、私は虚無主義者ではありません – モナド チュートリアルの呪いは解けると信じています! では、もう少し複雑な図を見てみましょう。友達に持っていく価値があるかどうかは、あなたが決めてください。
モナドは、プロジェクト マネージャーとのバケット ブリゲードです。プロジェクト マネージャーは、旅団の最初のメンバーを除くすべてのメンバーを支援します。バケツ旅団のメンバーは椅子に座り、前にバケツを置いています。
最初の人は何かを受け取り、それを使って何かを行い、それをバケツに入れます。その人は、旅団の次の人に引き継ぐのではなく、簡単すぎるでしょう! :-) – しかし、その人の後ろに立っているプロジェクト マネージャーに。
プロジェクト マネージャー (彼女の名前はbind、または>>=
) はバケットを受け取り、それをどうするかを決定します。彼女は最初の人のものをバケツから取り出し、それ以上苦労せずに目の前の人に渡すことにするかもしれません (それが IO モナドです)。彼女はバケツを捨てて旅団を終わらせることを選ぶかもしれません (それは ですfail
)。彼女は、目の前の人を迂回して、バケツを旅団の次のマネージャーに渡すことにするかもしれません (これNothing
はMaybe
モナドで起こります)。彼女はバケツから物を取り出して、一度に彼女の前の人に渡すことさえ決めるかもしれません! (これが List モナドです。) sequence ( >>
) の場合、彼女は目の前にいる人の肩を軽くたたくだけで、何かを渡す代わりに。
次の人がバケツ一杯の物を作ったら、その人はそれを次のプロジェクトマネージャーに渡します。次のプロジェクト マネージャーは、与えられたバケツをどうするかをもう一度考え、バケツの中のものを担当者に渡します。最後に、バケットは一連のプロジェクト マネージャーに戻されます。プロジェクト マネージャーは、オプションでバケットを操作できます (List
すべての結果を組み立てるモナドのように)。最初のプロジェクト マネージャーは、結果として大量のものを作成します。
構文の場合、do
各人は実際には、以前に行われたすべてのコンテキスト内でその場で定義された操作です。まるで、プロジェクト マネージャーがバケツにあるものだけでなく、値 (つまり、もの) も渡すかのように。旅団の前のメンバーによって生成されたもの。この場合のコンテキストの構築は、構文を使用する代わりにバインドとシーケンスを使用して計算を書き出すと、はるかに簡単に確認できます。do
連続する各「ステートメント」は、そのポイントに先行する操作内で構築された無名関数であることに注意してください。
() 値、IO モナド、およびreturn
操作は、上記のとおりです。
「しかし、これは複雑すぎます。なぜ人々はバケツを自分で降ろすことができないのでしょうか?」私はあなたが尋ねると聞きます。プロジェクト マネージャーは、そうしなければ作業を複雑にする多くの作業を舞台裏で行うことができます。私たちは、これらの旅団のメンバーを簡単にしようとしているので、彼らはあまり多くのことをする必要はありません. たとえば、Maybe モナドの場合、各人は、何も与えられていないかどうかを確認するために、与えられたものの値をチェックする必要はありません。プロジェクト マネージャーがその面倒を見てくれます。
「それなら、もしあなたが本当に各人の仕事を楽にしようとしているのなら、なぜ徹底的にやってみませんか? 人に物を取り、物を手渡すだけにして、プロジェクトマネージャーにバケツの心配をさせませんか?」それはしばしば行われ、人 (er、操作) をモナドに持ち上げるという特別な名前が付けられています。しかし、もう少し複雑なことをする人が必要な場合があります。そこでは、生成されたバケットを制御したい場合があります (たとえば、モナドNothing
の場合に返す必要があるかどうかなど)。Maybe
一般性が提供します。
ポイントは次のとおりです。
これで就寝時のチュートリアルは終了です。:-P
プログラミング以外の用語では:
FとG が随伴関手のペアで、FがGの随伴のままである場合、合成GF はモナドです。
プログラミングの外側 (FP だけでなく、すべてのプログラミングの外側) に、重要な意味で作用する、またはモナドのようであると言える概念/ものはありますか?
はい、実際にあります。モナドは、Curry-Howard 同型の拡張により、様相論理の「可能性」に直接関係しています。(参照:様相論理の判断的再構築。 )
これは非常に強い関係であり、論理的な側面の可能性に関連する概念は、圏論のモナドに関連する概念よりも直感的です。モナドを生徒に説明するために私が見つけた最良の方法は、この関係を利用していますが、同型を明示的に示していません。
基本的な考え方は、モナドがなければ、すべての式が同じ世界に存在し、すべての計算がその世界で行われるというものです。しかし、モナドでは多くの世界が存在する可能性があり、計算はそれらの間を移動します。(例えば、各ワールドは可変状態の現在の値を指定するかもしれません)
この見方では、モナドp
は「現在の世界から到達可能な可能性のある世界」を意味します。
特にt
がタイプの場合:
x :: t
タイプ t の何かが現在のワールドで直接利用可能であること
y :: p t
を意味します タイプ t の何かが現在のワールドから到達可能なワールドで利用可能であることを意味します
次に、return
現在の世界を到達可能な世界として使用できるようにします。
return :: t -> p t
そして>>=
、到達可能な世界で何かを利用し、その世界から追加の世界に到達することを可能にします。
(>>=) :: p t -> (t -> p s) -> p s
その>>=
ため、他のワールドを通る小さなパスから到達可能なワールドへのパスを構築するために使用できます。
世界は状態のようなものであるため、これは非常に簡単に説明できます。IO モナドのようなものについても、非常に簡単です。世界は、プログラムが外部世界と行ったすべての相互作用によって指定されます。
非終了の場合、2 つの世界で十分です。通常の世界と、無限に遠い未来の世界です。(2 番目の世界で >>= を適用することは許可されていますが、その世界で何が起こるかを観察することはほとんどありません。) 継続モナドの場合、継続が通常に使用される場合、世界は同じままであり、継続が使用される場合には追加の世界があります。ではありません (たとえば、callcc の場合)。
Mike Vanier によるこの優れた投稿から、
Haskell を他のプログラミング言語と区別する重要な概念の 1 つは、「モナド」の概念です。人々はこれを学ぶのが難しいと感じているようで (私もそうでした)、その結果、Web 上にはたくさんのモナドのチュートリアルがあり、そのうちのいくつかは非常に優れています (私は Jeff Newbern による All About Monads が特に好きです)。モナドのチュートリアルを書くことは、新しい Haskell プログラマーにとって通過儀礼であると言われています。しかし、多くのモナド チュートリアルの大きな問題の 1 つは、読者がすでに理解している既存の概念を参照して、モナドとは何かを説明しようとすることです (GHC コンパイラの主な作者である Simon Peyton-Jones によるプレゼンテーションでこれを見たことさえあります)。および一般的な Haskell grand poobah)。これは誤りです。その理由を説明します。
何かを説明しようとするとき、相手がすでに知っていることを参照して説明するのは自然なことです。これは、新しいものが他の人がよく知っているものといくつかの点で似ている場合にうまく機能します. 新しいものがそれを学ぶ人の経験から完全に外れると、それは完全に崩壊します。たとえば、火を見たことのない穴居人に火とは何かを説明しようとしているとしたら、何と答えますか? 「空気と水のクロスのようなものですが、暑いです...」 あまり効果的ではありません。同様に、量子力学の観点から原子が何であるかを説明することは問題があります。星の周りの惑星のように核の周りを周回し、「非局在電子雲」の概念はあまり意味がありません. ファインマンはかつて、誰も量子力学を本当に理解していないと言いましたが、直感的なレベルではそれは真実です. しかし、数学レベルでは、量子力学はよく理解されています。数学が実際に何を意味するのかについて、私たちは良い直感を持っていません。
これはモナドとどのように関係していますか?チュートリアル、ブログ投稿、Haskell メーリングリストで、モナドが「アクションのようなもの」または「コンテナのようなもの」という 2 つの直感的な方法のいずれかで説明されているのを何度も目にしました。何かがアクションとコンテナーの両方になるにはどうすればよいでしょうか? これらは別の概念ではありませんか?モナドはある種の奇妙な「アクティブコンテナ」ですか? いいえ、しかし要点は、モナドが一種のアクションまたは一種のコンテナであると主張することは正しくないということです。では、モナドとは何か?
答えは次のとおりです。モナドは純粋に抽象的な概念であり、おそらくこれまでに聞いたことのあるものとは根本的な関係はありません。モナドの概念は、私が知っている数学の中で最も抽象的な分野である圏論から来ています。実際、圏論の全体的なポイントは、数学の構造のすべてを抽象化して、一見異なる領域間 (たとえば、代数とトポロジーの間) の類似性と類似性を明らかにし、数学をその基本的な概念に凝縮することです。したがって、冗長性を減らします。(私はこれについてかなり長く続けることができますが、私が作ろうとしているポイントに戻りたいと思います。) Haskell を学んでいるほとんどのプログラマーは圏論についてあまり知らないと推測しているので、モナド彼らにとって何の意味もありません。だからといって、Haskell でモナドを使うために圏論のすべてを学ぶ必要があるというわけではありません (幸いなことに)。
記事の全文を読むには、投稿の上部にあるリンクにアクセスしてください。
実際には、私が扱ってきたほとんどのモナドは、ある種の暗黙のコンテキストのように振る舞います。
あなたと友人が共通の友人について会話しようとしているようなものです. あなたが「ボブ」と言うときはいつでも、あなたは両方とも同じボブを指していて、ボブがあなたの共通の友人であるという文脈のために、その事実はあなたの会話を通して暗示的にスレッド化されています.
もちろん、たまたまボブという名前のスキップ レベル マネージャー (友人ではない) について、上司 (友人ではない) と会話することもできます。ここでも、会話のコンテキスト内でのみ意味をなす暗黙の意味合いを伴う、別の会話を行うことができます。友達に対して行ったのとまったく同じ言葉を発することもできますが、文脈が異なるため、意味が異なります。
プログラミングでも同じです。のtell
動作は、現在のモナドによって異なります。情報を組み立てる方法 ( >>=
) は、現在のモナドによって異なります。考え方は同じですが、会話のモードが異なります。
なんてこった、会話のルールでさえ単項になる可能性があります。「私が言ったことを誰にも言わないで」は、参照がモナドrunST
をエスケープするのを防ぐのと同じ方法で情報を隠します。ST
明らかに、モナド変換子のスタックがあるように、会話はコンテキストのレイヤーとレイヤーを持つことができます。
それが役立つことを願っています。
さて、これは間違いなくすべてのプログラミングの外にあるモナドの非常に詳細な説明です。私はプログラマーなので、プログラミングの外にあることは知っていますが、それが話していることの半分も理解していません。
その種類のモナドを説明する YouTube の一連のビデオもあります。
それはあなたが本当に探していたものではないと思いますが...
それはあなたが誰と話しているかによります。説明は適切なレベルで行う必要があります。化学エンジニアへの説明は、数学者や財務マネージャーへの説明とは異なります。
最善のアプローチは、話している相手の専門知識に関連付けることです。原則として、順序付けはかなり普遍的な問題であるため、「最初に X を実行し、次に Y を実行する」と言う場所について、その人が知っていることを見つけるようにしてください。次に、通常のプログラミング言語がそれに関してどのように問題を抱えているかを説明してください。コンピューターに対して「X を実行してから Y を実行する」と言うと、コンピューターは次の入力を待たずにすぐに X と Y を実行しますが、その間に他の誰かのために Z を実行することはできません。「してから実行する」というコンピュータの考え方は、あなたのものとは異なります。したがって、プログラマーは、あなた (専門家) が説明する方法とは異なる方法でプログラムを作成する必要があります。これにより、あなたが言うこととプログラムが言うことの間にギャップが生じます。そのギャップを埋めるには時間とお金がかかります。
モナドを使用すると、「してから行う」のバージョンをコンピューターに入れることができるため、「X を行ってから Y を行う」と言うことができ、プログラマーは「{x ; y} を行う」と書くことができ、それはあなたが意味することを意味します。
私はそれらを、「バインド」できる計算の抽象化と考えるのが好きです。または、ブリトー!
はい、モナドはhaskell以外の概念から来ています。Haskellには、圏論から借用した多くの用語とアイデアがあります。これはそのうちの1つです。したがって、プログラマーではないこの人が圏論を研究した数学者であることが判明した場合は、「モナドは圏論のカテゴリーのモノイドです」とだけ言ってください。