関数の下で閉じられた集合、つまりフィボナッチ数列の加算を伴う整数に対して、バイナリ再帰を末尾再帰に変換する明確な方法があります。
(ハスケルを使用)
fib :: Int -> Int
fib n = fib' 0 1 n
fib' :: Int -> Int -> Int
fib' x y n
| n < 1 = y
| otherwise = fib' y (x + y) (n - 1)
これが機能するのは、目的の値y
と演算x + y
がありx + y
、整数と同じように整数を返すからy
です。
しかし、関数の下で閉じられていないセットを使用したい場合はどうすればよいでしょうか? リストを 2 つのリストに分割し、その 2 つのリストに対して同じことを行う関数を使用したいと考えています (つまり、バイナリ ツリーを再帰的に作成するようなものです)。別の関数が魔法のように、結果の分割を見ていつ停止するかを指示したときに停止します。 :
[1, 2, 3, 4, 5] -> [[1, 3, 4], [2, 5]] -> [[1, 3], [4], [2], [5]]
あれは、
splitList :: [Int] -> [[Int]]
splitList intList
| length intList < 2 = [intList]
| magicFunction x y > 0 = splitList x ++ splitList y
| otherwise = [intList]
where
x = some sublist of intList
y = the other sublist of intList
では、この二項再帰を末尾再帰に変換するにはどうすればよいでしょうか。Int + Int -> Int
(は入力と同じ) しかし ( は入力と同じではない) であるため、前の方法は明示的に機能しSplit [Int] -/> [[Int]]
ません。そのため、アキュムレータを変更する必要があります (私は推測します)。