スタック オーバーフローを防ぐために、単一の再帰関数に末尾再帰の最適化を適用できますが、相互再帰関数についてはどうでしょうか。
この回答は、F# で相互再帰関数を定義する方法を示しています。
let rec F() =
G()
and G() =
F()
生成されたネイティブ マシン コードまたはバイトコードが最終的に F と G の両方に末尾再帰の最適化が適用された 1 つの関数だけで構成されるように、このように定義されていますか? これはスタックオーバーフローを防ぎますか?
相互再帰関数の末尾呼び出しのアルゴリズムはどのように機能しますか?
一方、Haskell ではそのような構文は必要ありません。Haskell の遅延評価のせいでしょうか。または@augustssが示唆するように、Haskellコンパイラも上記と同じことをしていますか?