1

関数には再帰的な名前を付ける必要があるようです (それ自体を呼び出すため)。では、ラムダ関数はどのように再帰的になりますか?

ウィキペディアを検索したところ、これは「Yコンビネーター」で実行できると書かれています。私は数学理論のバックグループをあまり持っていません.「Yコンビネータ」がHaskell自身によって発見されたことを教えてくれます. Haskell 言語で "fix" キーワードと呼ばれる、私が試した:

Prelude> let fact = fix (\f n -> if n == 0 then 1 else n * (f (n-1)))

<interactive>:17:12: Not in scope: ‘fix’

失敗したようですが、「修正」キーワードを使用して期待したことを行うにはどうすればよいですか?

4

2 に答える 2

12

fixData.Functionはキーワードではなく、モジュールで定義された関数です。したがって、それを使用するには、そのモジュールをインポートする必要があります。

import Data.Function

またはGHCiで:

:m Data.Function
于 2016-02-19T09:53:34.163 に答える
2

fixと定義されている:

fix :: (a -> a) -> a
fix f = let x = f x in x

f (f (f (f ...)))つまり、入力関数の入れ子になったアプリケーションの無限のシーケンスfにいくつかのパラメーターに展開されますx

ラムダ関数にトップレベルの定義を与えることができます。

factF f n = if n == 0 then 1 else n * f (n - 1)

または同等:

factF :: (Int -> Int) -> (Int -> Int)
factF f = \n -> if n == 0 then 1 else n * f (n - 1)

この関数を提供して、関数を取得できますfix(Int -> Int)

fact :: (Int -> Int)
fact = fix factF

この定義を展開すると、

factF (factF (factF (factF ...)))
=> \n -> if n == 0 then 1 else (factF (factF (factF ...)))

怠惰のため、 の繰り返し適用は、適用された上記の関数がすぐに 1 に評価されるfactF場合にのみ評価されます。n /= 00

この展開でfactFは、それ自体への引数として提供されていることがわかります。これは、より小さなバージョンの に適用されますnfactNはラムダ関数と同じであるため、そこで同じことが起こっています.ラムダ内のパラメータはfラムダ自体であり、再帰的に呼び出すことができます.

于 2016-02-19T14:25:50.433 に答える