HaskellでSICP3章のストリームを書いてみたらすごかった
言語仕様を見て、これならSICP3章だろうと思ってやってみたら、ほとんどが2行(うち型宣言が1行)で書けてわろた。あとで解説とか書くかもしれないし書かないかもしれない。
module Main where addStream :: Num a => [a] -> [a] -> [a] addStream = zipWith (+) scaleStream :: Num a => a -> [a] -> [a] scaleStream factor = map (*factor) mulStream :: Num a => [a] -> [a] -> [a] mulStream = zipWith (*) integersStartingFrom :: Num a => a -> [a] integersStartingFrom n = n : integersStartingFrom (n + 1) ones :: Num a => [a] ones = repeat 1 integers :: Num a => [a] integers = integersStartingFrom 1 partialSums :: Num a => [a] -> [a] partialSums (x:xs) = x : addStream (repeat x) (partialSums xs) integrateSeries :: Fractional a => [a] -> [a] integrateSeries xs = mulStream xs (map recip integers) expSeries = 1.0 : integrateSeries expSeries cosSeries = 1.0 : integrateSeries (map negate sinSeries) sinSeries = 0.0 : integrateSeries cosSeries mulSeries :: Num a => [a] -> [a] -> [a] mulSeries (a:as) (b:bs) = a*b : addStream (scaleStream a bs) (mulSeries as (b:bs)) sqrtStream :: Fractional a => a -> [a] sqrtStream x = guesses where guesses = 1.0 : map improve guesses improve guess = average guess (x/guess) average a b = (a+b)/2 eularTransform :: Fractional a => [a] -> [a] eularTransform (x0:x1:x2:xs) = x' : eularTransform (x1:x2:xs) where x' = x2 - (square (x2 - x1)) / (x0 - 2*x1 + x2) square x = x * x piSummands :: Fractional a => a -> [a] piSummands n = 1.0/n : map negate (piSummands (n+2)) piStream :: Fractional a => [a] piStream = scaleStream 4 (partialSums (piSummands 1)) makeTableau :: ([a]->[a]) -> [a] -> [[a]] makeTableau t xs = xs : makeTableau t (t xs) acceleratedSequence :: ([a]->[a]) -> [a] -> [a] acceleratedSequence t xs = map head (makeTableau t xs) ln2Summands :: Fractional a => a -> [a] ln2Summands n = 1/n : map negate (ln2Summands (n+1)) ln2Stream :: Fractional a => [a] ln2Stream = partialSums (ln2Summands 1) geometricSeris :: Num a => a -> a -> [a] geometricSeris a r = map ((a*).(r^)) (integersStartingFrom 0) polySeries :: Num a => a -> [a] polySeries = geometricSeris 1 applySeries :: Num a => [a] -> a -> [a] applySeries series x = (partialSums (mulStream series (polySeries x))) integral :: Num a => [a] -> a -> a -> [a] integral integrand initial dt = int where int = initial : addStream (scaleStream dt integrand) int solve' :: Num a => (a->a) -> a -> a -> [a] solve' f y0 dt = y where y = integral dy y0 dt dy = map f y solve :: Fractional a => (a->a) -> a -> Int -> a solve f y0 n = (solve' f y0 dt) !! n where dt = 1 / (fromIntegral n) solve2nd :: Num a => a -> a -> a -> a -> a -> [a] solve2nd a b dt y0 dy0 = y where y = integral dy y0 dt dy = integral ddy dy0 dt ddy = addStream (scaleStream a dy) (scaleStream b y) solve2nd_gen :: Num a => (a -> a -> a) -> a -> a -> a -> [a] solve2nd_gen f dt y0 dy0 = y where y = integral dy y0 dt dy = integral ddy dy0 dt ddy = zipWith f dy y