4

私はVisual Studioをいじっていて、それを発見しました

delegate RecursiveDelegate RecursiveDelegate();

有効なデリゲート定義です。

関数型プログラミングの経験はあまりありませんが、このパターンが関数型プログラミングで実際に役立つのか、それともセマンティクスの単なる好奇心なのか疑問に思っていました。この質問を次の 2 つの方法で行いたいと思います。

  1. 副作用のある文脈で。これは実際には、アルゴリズムの実際のタスクが副作用として実行され、関数の新しいバージョンが戻り値である関数型言語で反復学習アルゴリズムをモデル化する中途半端な方法であることがわかります。これはできていますか?
  2. 副作用のないコンテキストで。これは原則として役に立たないと思いますが、間違っていると非常に興味があります。RecursiveDelegate() の実装に副作用がないと仮定した場合、これは役に立ちますか?
4

2 に答える 2

1

厳密には再帰デリゲートではない同様のコードの例がありますが、それに近いものです。「Y-Combinator」が近づいてきました。率直に言って、実際にどのように機能するかはわかりませんが、再帰関数を定義するために使用されます。

定義する必要があるファンキーなコードは次のとおりです。

public delegate T S<T>(S<T> s);

public static T U<T>(S<T> s)
{
    return s(s);
}

public static Func<A, Z> Y<A, Z>(Func<Func<A, Z>, Func<A, Z>> f)
{
    return U<Func<A, Z>>(r => a => f(U(r))(a));
}

再帰関数を 1 行で定義できるようになりました。

階乗:

var fact = Y<int, int>(_ => x => x == 0 ? 1 : x * _(x - 1));
var fact5 = fact(5); // == 120
var fact6 = fact(6); // == 720
var fact7 = fact(7); // == 5040

フィボナッチ:

var fibo = Y<int, int>(_ => x => x <= 1 ? 1 : _(x - 1) + _(x - 2));
var fibo5 = fibo(5); // == 8
var fibo6 = fibo(6); // == 13
var fibo7 = fibo(7); // == 21

コードで私のお気に入りの行は calls(s)です。真剣に、誰かが頭の中でそれを正すことができれば、彼らは天才です! 全体どころかU<Func<A, Z>>(r => a => f(U(r))(a))

于 2013-08-17T06:22:17.417 に答える