7

一般的に、私の推論に何か問題があるため、頭痛がします。

  1. 1 セットの引数の場合、参照透過関数は常に 1 セットの出力値を返します。

  2. つまり、そのような関数は真理値表 (1 セットの引数に対して 1 セットの出力パラメーターが指定されているテーブル) として表すことができます。

  3. そのような関数の背後にあるロジック(順次ではなく) 組み合わせになります。

  4. つまり、純粋な関数型言語 (rt 関数のみを持つ) では、組み合わせロジックのみを記述できます。

最後のステートメントはこの推論から導き出されたものです、明らかに誤りです。つまり、推論に誤りがあるということです。[質問: この推論のどこに誤りがありますか?]

UPD2. 皆さん、面白いことをたくさん言っていますが、私の質問には答えていません。私は今それをより明確に定義しました。質問の定義をめちゃくちゃにしてすみません!

4

5 に答える 5

6

質問: この推論のどこに誤りがありますか?

参照透過関数では、その動作を表すために無限の真理値表が必要になる場合があります。組み合わせ論理で無限回路を設計するのは難しいでしょう。

別のエラー: 順序ロジックの動作は、状態から状態への関数として純粋に機能的に表すことができます。実装では、これらの状態が時間的に連続して発生するという事実は、状態が時間とともにどのように進化するかを記述する純粋に参照透過的な関数を定義することを妨げるものではありません。

于 2010-07-17T00:25:41.527 に答える
3

編集:実際の質問のブルズアイを見逃したようですが、私の答えはかなり良いと思うので、そのままにしておきます:-)(以下を参照)。

質問をより簡潔に言い表すと、次のようになると思います。

まず、C のような命令型言語を使用して、変数を定義した後に変数を変更できないように作成したとします。例えば:

int i;

for (i = 0;  // okay, that's one assignment
     i < 10; // just looking, that's all
     i++)    // BUZZZ!  Sorry, can't do that!

さて、あなたのforループがあります。whileループを維持できますか?

while (i < 10)

確かに、しかしそれはあまり役に立ちません。 i変更できないため、永久に実行されるか、まったく実行されないかのいずれかです。

再帰はどうですか?はい、再帰を維持できますが、それでも十分に便利です。

int sum(int *items, unsigned int count)
{
    if (count) {
        // count the first item and sum the rest
        return *items + sum(items + 1, count - 1);
    } else {
        // no items
        return 0;
    }
}

さて、関数では状態を変更しませんが、変数は変化する可能性があります。変数が関数に渡されると、ロックされます。ただし、関数を再度呼び出すことができます (再帰)。これは、まったく新しい変数のセットを取得するようなものです (古い変数は同じままです)。との複数のインスタンスがありますがitemscountsum((int[]){1,2,3}, 3)常に に評価される6ため、必要に応じてその式を に置き換えることができ6ます。

私たちはまだやりたいことを何でもできますか?100%確実ではありませんが、答えは「イエス」だと思います。ただし、クロージャーがある場合は確かにできます。


あなたはそれを正しく持っています。アイデアは、変数が定義されると、再定義できないということです。同じ変数を指定すると、参照透過式は常に同じ結果値を生成します。

純粋に関数型の言語である Haskell を検討することをお勧めします。厳密に言えば、Haskell には「代入」演算子がありません。例えば:

my_sum numbers = ??? where
    i     = 0
    total = 0

ここでは、i と total をインクリメントする "for ループ" を書くことはできません。ただし、すべてが失われるわけではありません。再帰を使用して、新しいiとを取得し続けるだけtotalです。

my_sum numbers = f 0 0 where
    f i total =
        if i < length numbers
            then f i' total'
            else total
        where
            i' = i+1
            total' = total + (numbers !! i)

(これは Haskell でリストを合計するばかげた方法ですが、単一の割り当てに対処する方法を示していることに注意してください。)

次に、この非常に命令的なコードを考えてみましょう。

main = do
    a <- readLn
    b <- readLn
    print (a + b)

実際には、次の構文糖衣です。

main =
    readLn >>= (\a ->
    readLn >>= (\b ->
    print (a + b)))

main がステートメントのリストで構成される関数である代わりに、main は Haskell が実行する IO アクションであり、アクションが定義され、バインド操作と一緒に連鎖されるという考え方です。また、関数を使用して、何もせずに任意の値を生成するアクションを定義できますreturn

bind と return はアクションに固有のものではないことに注意してください。それらは、あらゆる種類のファンキーなことを行うために、自分自身を Monad と呼ぶ任意の型で使用できます。

明確にするために、 を検討してreadLnください。 readLn実行されると、標準入力から行を読み取り、その解析値を生成するアクションです。その値で何かをするために、変数に格納することはできません。参照透過性に違反するからです。

a = readLn

これが許可されている場合、 a の値は世界に依存し、 を呼び出すたびに異なります。readLnつまり、readLn参照透過性がなくなります。

代わりに、アクションを処理する関数に readLn アクションをバインドし、次のように新しいアクションを生成します。

readLn >>= (\x -> print (x + 1))

この式の結果はアクション値です。Haskell がソファから降りてこのアクションを実行すると、整数を読み取り、インクリメントして出力します。アクションの結果を、その結果で何かを行う関数にバインドすることにより、状態の世界で遊んでいる間、参照の透過性を維持することができます。

于 2010-07-16T21:28:13.330 に答える
2

私が理解している限りでは、参照透過性とは次のことを意味します。特定の関数が同じ引数で呼び出された場合、常に同じ結果が得られるということです。したがって、学校で学んだ数学関数は参照透過的です。

純粋に関数型の言語で物事がどのように行われるかを学ぶためにチェックアウトできる言語はHaskellです。たとえば、 Reader モナドやState モナドのような「更新可能なストレージの可能性」を使用する方法があります。純粋に機能的なデータ構造に興味がある場合は、岡崎氏を読むとよいでしょう。

そうです、その通りです。haskell のような純粋な関数型言語での評価の順序は、非関数型言語の場合のように重要ではありません。副作用がなければ、他の何かの前後に何らかの処理を行う理由がないからです。一方の入力が他方の出力に依存しない限り、またはモナドのような手段が機能する場合を除きます。

真理値表の質問についてはよくわかりません。

于 2010-07-16T20:40:16.000 に答える
1

質問に答える私の刺し傷は次のとおりです。

どのようなシステムも、大小を問わず組み合わせ関数として記述できます。

純粋関数は組み合わせ論理しか扱えないという推論に何の問題もありません。それは本当です。関数型言語はそれをある程度隠しているだけです。

たとえば、ゲーム エンジンの動作を真理値表または組み合わせ関数として説明することもできます。

「ゲーム全体の現在の状態」をゲーム エンジンとキーボード入力が占有する RAM として取り込み、「1 フレーム後のゲームの状態」を返す決定論的関数がある場合があります。戻り値は、入力のビットの組み合わせによって決まります。

もちろん、意味のある正常な関数では、入力は整数、小数、ブール値のブロックに解析されますが、これらの値のビットの組み合わせによって関数の出力が決定されます。

また、基本的なデジタル ロジックは真理値表で記述できることにも注意してください。それが、たとえば 4 ビット整数の演算以外には行われない唯一の理由は、真理値表のサイズが指数関数的に大きくなるためです。

于 2010-07-16T23:24:25.690 に答える
0

あなたの推論の誤りは次のとおりです。
「これは、そのような関数を真理値表として表すことができることを意味します」。

関数型言語の参照透過性のプロパティから、それを結論付けます。これまでの結論はもっともらしく聞こえますが、論理ゲートの固定入力とは対照的に、関数がコレクションを入力として受け入れ、それらを処理できることを監督します。

したがって、関数は論理ゲートではなく、実際の (実行時に決定される) 入力に応じた論理ゲートの構築計画です。

あなたのコメントにコメントするには:関数型言語は、ステートレスですが、アクセスされるたびに状態を最初から構築することにより、状態マシンを実装できます。

于 2010-07-16T23:09:59.617 に答える