naive Haskell fizzbuzz solutionに関する質問には、iterates forwardという実装を提案し、増加する素数の二次コストを避け、モジュロ除算を(ほぼ)完全に破棄しました。私はそれがData.List.unfoldr
を使用して書き換え提案し、さらにプロンプトとしてunfoldr対zipの効率
fizz :: Int -> String
fizz = const "fizz"
buzz :: Int -> String
buzz = const "buzz"
fizzbuzz :: Int -> String
fizzbuzz = const "fizzbuzz"
fizzbuzzFuncs = cycle [show, show, fizz, show, buzz, fizz, show, show, fizz, buzz, show, fizz, show, show, fizzbuzz]
toFizzBuzz :: Int -> Int -> [String]
toFizzBuzz start count =
let offsetFuncs = drop (mod (start - 1) 15) fizzbuzzFuncs
in take count $ zipWith ($) offsetFuncs [start..]
:ここでは、コードです。 unfoldr
バージョンはこのコードの明白で簡単な変更であるため、私の質問に答えたい人が重要であると主張しない限り、ここには入力しません(コードレビューでOP overのスポイラーはありません)。しかし、私はzipWith
と比較して、unfoldr
ソリューションの相対的効率について質問があります。私はもはやハスケルの新生児ではありませんが、私はハスケルの内部についての専門家ではありません。
unfoldr
ソリューションは、start
から簡単に展開できるので、[start..]
の無限リストは必要ありません。私の考えでは、それがために頼まれるようzipWith
ソリューションは[start..]
の連続する各要素をmemoizeしない
- です。 [start ..]の先頭への参照が保持されていないため、各要素が使用されて破棄されます。したがって、メモリが消費されているのは
unfoldr
です。 unfoldr
のパフォーマンスとそれが常にインライン化されるようにするための最近のパッチについての懸念は、まだ達成していないレベルで行われています。
私はメモリ消費量は同じですが、相対的な性能については考えていないと思います。より多くの情報を得たHaskellersが私にこれを理解させるように指示することができます。
unfoldr
は、他の解決策がより表現力豊かであっても、シーケンスを生成するのに自然なようです。私は実際のパフォーマンスについてもっと理解する必要があることを知っています。
注意(何らかの理由で、私はそのレベルで理解する方がはるかに簡単にfoldr
を見つける。):Maybe
のunfoldr
の使用は、私も問題を調査開始前に、私に起こった最初の潜在的なパフォーマンスの問題でした(と私が完全に理解している最適化/インライン化の議論のビットのみ)。だから私はすぐにMaybe
の心配を止めることができました(最近のバージョンのHaskellを参照)。
あなたが話しているコストは、素数の数を増やすことを意味することを明確にする必要があります。 – dfeuer
@dfeuer完了。あなたの答えをもう一度おねがいします。 – itsbruce