widzę to jako ogólną formę silni funkcji w Haskell:Czy można napisać funkcję czynnikową tak szybko, jak "podręcznik" w inny sposób?
factorial :: (Integral a) => a -> a
factorial n = product [1..n]
Rozumiem, że jest to najbardziej elegancki sposób, ale kiedy napisać własny funkcji rekurencyjnej, aby to zrobić, to znacznie wolniej:
factorial :: (Integral a) => a -> a
factorial 1 = 1
factorial n = n * factorial (n - 1)
Czy pierwsze rozwiązanie nie musi zrobić prawie wszystkiego, co robi pierwszy, wewnętrznie? Jak to jest o wiele szybciej? Czy można napisać coś tak szybko, jak pierwsze rozwiązanie bez użycia fantazyjnej listy lub funkcji produktu?
Fuzja, chociaż ważna, jest o wiele * mniej * ważna w tym przypadku niż kombinacja optymalizacji ogona i analizy ostrości. Fusion prawdopodobnie sprawia, że jest kilka razy szybszy, ale pozostałe powstrzymują go przed wysadzeniem. Użycie 'foldl'' pozwala uniknąć tak dużego polegania na analizie dokładności. – dfeuer
@dfeuer Zgadzam się, ale OP szuka powodu, dla którego wersja "produktu" jest szybsza. Optymalizacja ogona jest błogosławieństwem dla drugiej wersji, a analiza trafności dotyczy obu wariantów. To pozostawia syntezę jako główną siłę wersji 'foldl'. – Alec
Ich rekurencyjna wersja nie jest rekursywna. Porównaj szybkość ich rekurencyjnej wersji z szybszą wersją z produktem niezwiązanym ze sobą: '{- # NOINLINE product_ni # -} product_ni :: [Integer] -> Integer; product_ni = product'. – dfeuer