C#でモナドを実装する最良の方法は何ですか?特定の実装戦略があるか、またはすべてのモナドが別の方法で実装されていますか?C#でモナドを実装する最良の方法は何ですか
答えて
ちょうどそれにコメントするのではなく、質問に答えるために、おそらくLinqはC#でモナディック変換を実行する最前線の方法です。 Linqメソッド連鎖は、遅延評価され、順序付けされたリスト処理操作のセットにすぎません。
もちろん、Linqはロケット科学ではありません。あなたの平均的な大学レベルのプログラミングコース以上のものですが、まだまだです。これは一連の拡張メソッドであり、それぞれが実行すべきロジックを含むプレースホルダーの列挙型(モナド)とそのデータソース(別のモナドカプセル化でもよい)への参照を生成します。基本的なLinqライブラリに追加の拡張機能を追加したり、機能の穴を埋めたり、特定のニーズを満たすカスタムアクションを実行することができます。
また、実際に何かを行うために、独自のモナディックメソッド連鎖フレームワークを作成することもできます。 「流暢な」コーディングインターフェイスを持つと説明されているフレームワークやライブラリは、ほとんどがモナドベースのライブラリです。流暢なユニットテストアサーション、流暢なORM構成、さらには流暢なドメインUIマッピング拡張があります。
C#でモナドライブラリーを実装するのは、通常、静的クラスとスタティックメソッドを使用して行われます。静的メソッドは、意図した用途以外からはアクセスできない1つ以上のモナドタイプを使用します。例えば、ここでは整数の加算や減算を行い、基本的なモナドライブラリは次のとおりです。
public static class MonadicArithmetic
{
public static Monad Take(int input) { return new Monad(input); }
public class Monad
{
int theValue;
internal Monad(int input) { theValue = input; }
public Monad Add(int input){ return new Monad(theValue + input); }
public Monad Subtract(int input){ return new Monad(theValue - result); }
public int Value { get { return theValue; } }
}
}
...
//usage
var result = MonadicArithmetic.Take(1).Add(2).Subtract(1).Value; //2
明らかにこれは非常に基本的であり、すべての操作は、「熱心に」実行されます。具体的な値は、コードを消費することによって要求されるまで何も操作は行われませんを除いて、
public static class MonadicArithmetic
{
public static Monad Take(int input) { return new Monad(input); }
public class Monad
{
//Change the "value keeper" into a Func that will return the value;
Func<int> theValue;
//the constructor now turns the input value into a lambda
internal Monad(int input) { theValue =()=>input; }
//and another constructor is added for intra-class use that takes a lambda
private Monad(Func<int> input) { theValue = input; }
//And now the methods will create new lambdas that call the existing lambdas
public Monad Add(int input){ return new Monad(()=>theValue() + input); }
public Monad Subtract(int input){ return new Monad(()=>theValue() - input); }
//Finally, our Value getter at the end will evaluate the lambda, unwrapping all the nested calls
public int Value { get { return theValue(); } }
}
}
同じ使用:
それらの操作が複雑であれば、これは最適ではないかもしれないので、代わりに、さんは「なまけ」、それらを実行してみましょう//Each call just adds a shell to the nested lambdas
var operation = MonadicArithmetic.Take(1).Add(2).Subtract(1);
...
//HERE's the payoff; the result is not evaluated till the call to Value_get() behind the scenes of this assignment.
var result = operation.Value;
ただし、これに問題があります。これらのメソッドは単に入力値を取り、ラムダでそれらを参照します。問題は、値のスコープが含まれるメソッド(ラムダが評価されるのに十分な長さではないことを意味する)に依存することです。 Value()ゲッターが呼び出されると、ラムダが評価され、これらの範囲外の変数がすべて参照されます。代わりに、私たちはラムダと同じくらい長く生きるものに値を残すべきです。モナドは明らかな選択肢です。考えられる解決策は次のとおりです。
public static class MonadicArithmetic
{
public static Monad Take(int input) { return new Monad(input); }
public class Monad
{
//Our value keeper is now a pure function that requires no external closures
Func<Func<int>, int, int> operation;
//and we add two new private fields;
//a hook to a lambda that will give us the result of all previous operations,
Func<int> source;
//... and the value for the current operation.
private int addend;
//our constructor now takes the value, stores it, and creates a simple lambda
internal Monad(int input) { addend = input; operation =()=>addend; }
//and our private constructor now builds a new Monad from scratch
private Monad(Func<int> prevOp, Func<Func<int>, int, int> currOp, int input)
{
source = prevOp,
operation = currOp,
addend = input;
}
//The methods will create new Monads that take the current Monad's value getter,
//keeping the current Monad in memory.
public Monad Add(int input)
{
return new Monad(this.Result, (f,i)=>f()+i, input);
}
public Monad Subtract(int input)
{
return new Monad(this.Result, (f,i)=>f()-i, input);
}
//And we change our property to a method, so it can also
//be used internally as a delegate
public int Result() { return operation(source, addend); }
}
}
//usage
var operations = MonadicArithmetic.Take(1).Add(3).Subtract(2);
//There are now 3 Monads in memory, each holding a hook to the previous Monad,
//the current addend, and a function to produce the result...
...
//so that here, all the necessary pieces are still available.
var result = operations.Result();
これはモナディックライブラリの基本パターンです。全体を開始する静的メソッドは、Linqが使用するスタイルである拡張メソッドです。メソッドチェーンのルートが最初の値になる:
//using an "identity function" to convert to a monad
var operations = 1.AsMonad().Add(2).Subtract(3);
//performing the conversion implicitly from an overload of Add()
var operations = 1.Add(2).Subtract(3);
LINQの目的のために、そのライブラリはIEnumerableをを取るとのIEnumerableを返す拡張メソッドであることに特にエレガントなので、変換プロセスは、任意の過負荷なしで処理され、または明示的なメソッド呼び出し。しかし、翻訳可能な式ツリーを隠すIQueryableオブジェクトは.NET 3.5では新しいアイデアであり、AsQueryable()メソッドを使用して明示的にコレクションをIQueryableに変換する必要があります。
乾杯実際の答え:)しかし、私はまだあなたの答えの戦略のいくつかのまっすぐな前方C#のコードや詳細を表示するに失敗します –
私はあなたが何を記述しているとは思わないMonadの定義を満たしています。それはちょうど流暢なインターフェイスと思われる。 Monadsは、アイデンティティ、バインド&リターンといった特定の操作を実装する必要があります。 Linqはこれらの操作を実装しているのでモナドです。バインド操作は、例えば、 'SelectMany'拡張メソッドです。 – Enigmativity
私は対立しています。 Wikipedia: "関数型プログラミングでは、モナドは、(ドメインモデルのデータではなく)計算を表現するために使用される抽象的なデータ型コンストラクタの一種で、パイプラインを構築するためにアクションを連鎖させることができます。モナドによって提供される追加の処理規則で装飾されています。 "これが成り立つならば、 "文法構造"(有効なメソッドを制御するために内部型の使用を必要とする)を持つ流暢なインターフェースは、モナドとしてラベル付けできます。この場合、私はモナド(Take)に変換し、変換(Add/Subtract)して返します。 – KeithS
- 1. SpringセキュリティでRESTを実装する最良の方法は何ですか?
- 2. LAN上でデバイスディスカバリを実装する最良の方法は何ですか
- 3. Androidで「スタブ」を実装する最良の方法は何ですか?
- 4. C#でこのフローを実装する最良の方法
- 5. Railsアプリケーションでスキニングを実装する最も良い方法は何ですか
- 6. tensorflowで3Dコンボリューションを実装する最も良い方法は何ですか?
- 7. iOSアプリでフォルダを実装する最も良い方法は何ですか?
- 8. .NETでこれを実装する最も良い方法は何ですか?
- 9. Webサービスのログインを実装する最良の方法は何ですか?
- 10. 「人気コンテンツ」ディスプレイを実装する最良の方法は何ですか?
- 11. 水平スクロールカルーセルコンポーネントを実装する最良の方法は何ですか?
- 12. C++でハッシュローテーションメソッドを実装する最善の方法は何ですか?
- 13. C++で分数型を実装する最も良い方法は何ですか?
- 14. HATEOASのリンクリレーションシップをXMLで実装する最良の方法は?
- 15. C#のTextBoxに入力制限を実装する最良の方法は何ですか?
- 16. Railsアプリケーションで投票を実装する最良の方法は?
- 17. C#でインタプリタを書く:命令を実装する最良の方法は?
- 18. Objective-C roguelike内で複数のレベルを実装する最良の方法は?
- 19. C#で高解像度のDateTime.UtcNowを実装する最も良い方法は?
- 20. C/C++でテキストファイルを暗号化する最良の方法は何ですか?
- 21. javascriptでキューを実装する最も良い方法は?
- 22. httpでセキュリティを実装する最も良い方法は
- 23. SharePoint 2010でダイナミックメニューを実装する最良の方法はどれですか?
- 24. アンドロイドでWebベースのアプリケーションを実装する最良の方法
- 25. C#でREST APIを実装するには良い方法
- 26. iOSでは、スライド式の「引き出し」を実装する最良の方法は何ですか
- 27. php4でtry catchを実装する最良の方法
- 28. iPhoneプロジェクトでAdWhirlを実装する最良の方法
- 29. Zend Frameworkで多言語を実装する最良の方法
- 30. cakephp 2.0でoauth consumerを実装する最良の方法
LINQ。 (例:http://lorgonblog.wordpress.com/2007/12/07/monadic-parser-combinators-a-noteworthy-aside/) – Brian
このhttp://blogs.msdn.com/b/wesdyer/archive/ 2008/01/11/the-marvels-of-monads。aspxも素敵に見えます、悲しいかな、これは実装戦略の唯一の例です –
Really LINQ(http://stackoverflow.com/questions/1418106/how-much-is-there-to-linq/1418176#1418176) – Dario