Haskellで小さなツールを作成した経験があり、特にinteract
標準入力を処理して標準出力にパイプするフィルター(を使用)を作成するために、非常に直感的に使用できます。
最近、通常の約10倍のサイズのファイルでこのようなフィルターを使用しようとしましたが、Stack space overflow
エラーが発生しました。
いくつか読んだ後(こことここなど)、スタックスペースを節約するための2つのガイドラインを特定しました(経験のあるHaskellers、正しくないものを書いたら修正してください):
- 末尾再帰ではない再帰関数呼び出しは避けてください(これは末尾呼び出しの最適化をサポートするすべての関数型言語で有効です)。
seq
式が縮小される前に大きくなりすぎないように、部分式の早期評価を強制的に導入します(これはHaskell、または少なくとも遅延評価を使用する言語に固有です)。
seq
コードに5回または6回の呼び出しを導入した後、ツールは再びスムーズに実行されます(より大きなデータでも)。ただし、元のコードはもう少し読みやすいと思います。
私は経験豊富なHaskellプログラマーではないのでseq
、この方法で紹介するのが一般的なプラクティスであるかどうか、またseq
Haskellの製品コードで通常どのくらいの頻度で表示されるかを尋ねたいと思いました。または、seq
あまり頻繁に使用することを避けながら、スタック領域をほとんど使用しないテクニックはありますか?
1
あなたが説明したような最適化は、ほとんど常にコードを少しエレガントにしません。
—
ロバートハーベイ
@Robert Harvey:スタック使用量を低く抑えるための代替技術はありますか?私は自分の関数を別の方法で書き直さなければならないことを想像していますが、確立されたテクニックがあるかどうかはわかりません。私の最初の試みは、末尾再帰関数を使用することでしたが、これは問題を完全には解決できませんでした。
—
ジョルジオ