この質問を投稿してから1年が経過しています。それを掲示した後、私は数カ月間ハスケルに掘り下げた。私はそれをすごく楽しんだが、私はMonadsに掘り下げる準備ができていたときと同じようにそれを置いた。私は仕事に戻り、プロジェクトに必要な技術に焦点を当てました。
そして最後の夜、私は来て、これらの反応を再読しました。 最も重要なのはです。私は、the Brian Beckman video誰かmentions aboveのテキストコメントでthe specific C# exampleを再読しました。それは私がここにそれを直接掲示することを決めたように、とても完全に明確で明るいものでした。私は正確を理解して好きなので、このコメントを、私は...私はがモナド...または少なくとも非常に接近していることを私は実際にC#でいくつかのことを書いて実現する、とに努力しているものモナド
を感じていないだけ同じ問題を解決する。
だから、ここのコメントがあります - これはsylvanによってthe comment hereからのすべての直接の引用です:
これはかなりクールです。それは少し抽象です。実際の事例がないために、どのモナドがすでに混乱しているのか分からない人がいると思います。
私が遵守しようとすると、実際にはっきりするように、私はC#で例を挙げます。私は終わりに相当するハスケルを追加し、あなたには、IMOのモナドが実際に役に立つようになる、涼しいハスケルの構文的な砂糖を示します。
ハスケルでもっとも簡単なモナドの1つは、「多分モナド」と呼ばれています。 C#では、MaybeタイプはNullable<T>
と呼ばれています。これは、基本的には、有効で値があるか、または「null」で値がない値の概念をカプセル化したちょっとしたクラスです。
このタイプの値を組み合わせるためのモナドの中にスティックするのに便利なのは、失敗の概念です。私。複数のnull可能な値を見て、いずれか1つがnullになるとすぐにnull
を返したいと考えています。たとえば、辞書などの中でたくさんのキーを検索し、最後にすべての結果を処理して何らかの方法で結合したい場合に便利ですが、いずれかのキーが辞書にない場合は、あなたは全体のためにnull
を返すしたいと思います。これは、手動でnull
とリターンのために、それぞれのルックアップをチェックする必要が面倒になるので、私たちはモナドのポイントの一種である(バインド演算子内でこのチェックを非表示にすることができ、我々は、コードが容易になり、バインドオペレータで記帳を隠します私たちは細部について忘れることができるので使用する)。
これはすべてのことを動機づけするプログラムです(後ほどBind
を定義します。なぜこれが良いのかを示すためです)。
class Program
{
static Nullable<int> f(){ return 4; }
static Nullable<int> g(){ return 7; }
static Nullable<int> h(){ return 9; }
static void Main(string[] args)
{
Nullable<int> z =
f().Bind(fval =>
g().Bind(gval =>
h().Bind(hval =>
new Nullable<int>(fval + gval + hval))));
Console.WriteLine(
"z = {0}", z.HasValue ? z.Value.ToString() : "null");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
さて、すでにC#でNullable
ためにこれを行うためのサポートは、(あなたが一緒にNULL可能int型を追加することができますし、どちらかがnullの場合はnullを取得)があることを一瞬無視。そのような機能はないと推測してみましょう。特別な魔法を持たないユーザー定義のクラスです。ポイントは、Bind
関数を使用して、変数をNullable
値の内容にバインドしてから、何も変わっていないふりをして、通常のintのように使用してそれらを一緒に追加するということです。最後にnullableに結果をラップし、nullable(f
,g
またはh
のいずれかがnullを返す場合)またはf
,g
、およびh
を合計した結果になります。 (これはBind
オペレータは、変数にのみ、これまで有効な行の値を渡されることを確認しますことを、我々はLINQでの変数にデータベース内の行を結合し、そしてそれをものを行うことができる方法の類似した知識で安全です)。
f
,g
、およびh
のいずれかをnullに戻すと、すべてがnullを返すことがわかります。
明らかに、バインド演算子がこのチェックを行う必要があり、ヌル値に遭遇した場合はnullを返し、それ以外の場合はNullable
構造体内の値をラムダに渡します。
はここBind
オペレータです:ここ
public static Nullable<B> Bind<A,B>(this Nullable<A> a, Func<A,Nullable<B>> f)
where B : struct
where A : struct
{
return a.HasValue ? f(a.Value) : null;
}
種類はちょうどビデオのようです。 M a
(この場合はC#の構文ではNullable<A>
)、関数はa
からM b
(C#の構文ではFunc<A, Nullable<B>>
)です。M b
(Nullable<B>
)を返します。
コードでは、nullableに値が含まれているかどうかを確認し、値があればそれを抽出して関数に渡します。それ以外の場合はnullを返します。つまり、Bind
演算子がすべてのヌルチェックロジックを処理します。 Bind
という値がnullでない場合に限り、その値はラムダ関数に渡されます。そうでない場合、早期にベールアウトされ、式全体がnullになります。 これは、モナドを使って書いたコードがこのヌルチェックの振る舞いから完全に自由になることを可能にします。ちょうどBind
を使用し、モナド値(例コードではfval
,gval
およびhval
) Bind
はそれらを渡す前にnullをチェックする世話をします。
モナドでできることの他の例があります。たとえば、Bind
オペレータに入力文字ストリームを処理させ、それをパーサコンビネータを書き込むために使用することができます。それぞれのパーサーコンビネータは、バックトラッキング、パーサの失敗などのことを完全に無視することができます。ちょうど間違っていないかのように、小さなパーサーを組み合わせるだけです。Bind
の賢明な実装では、困難なビット。その後、誰かがモナドにログを追加するかもしれないが、モナドを使用しているコードは変更されない。なぜなら、すべての魔法はBind
オペレータの定義で起こり、コードの残りの部分は変更されないからである。
最後に、Haskellで同じコードを実装しています(--
はコメント行を開始します)。
-- Here's the data type, it's either nothing, or "Just" a value
-- this is in the standard library
data Maybe a = Nothing | Just a
-- The bind operator for Nothing
Nothing >>= f = Nothing
-- The bind operator for Just x
Just x >>= f = f x
-- the "unit", called "return"
return = Just
-- The sample code using the lambda syntax
-- that Brian showed
z = f >>= (\fval ->
g >>= (\gval ->
h >>= (\hval -> return (fval+gval+hval))))
-- The following is exactly the same as the three lines above
z2 = do
fval <- f
gval <- g
hval <- h
return (fval+gval+hval)
あなたが最後に素敵なdo
表記を見ることができるように、それがまっすぐに不可欠のコードのように見えます。実際、これは設計によるものです。モナドは、命令プログラミング(可変状態、IOなど)のすべての有用なものをカプセル化するために使用でき、この素敵な命令的な構文を使用していますが、カーテンの後ろにはすべてモナドだけでなく、バインド演算子の巧妙な実装です! クールなことは、>>=
とreturn
を実装して、独自のモナドを実装できることです。そしてもしそうすれば、それらのモナドはdo
表記を使うことができます。つまり、基本的に2つの関数を定義するだけで、あなた自身の小さな言語を書くことができます!
実際はC#3.0の開発者です。 .NET 3.5と間違えないでください。それ以外に、すてきな質問。 – Razzie
LINQクエリ式はC#3のモナドの動作の例であることを指摘しておきましょう。 –
私はまだ重複した質問だと思っています。 http://stackoverflow.com/questions/2366/can-anyone-explain-monadsの回答の1つはhttp://channel9vip.orcsweb.com/shows/Going+Deep/Brian-Beckman-Dont-fear-にリンクしています。 the-Monads /、コメントの1つが非常に素晴らしいC#の例を持っています。 :) – jalf