Részkifejezések megosztása

Részkifejezések megosztása

Megosztás (sharing): emlékezés korábban már kiszámított konstans értékekre

Milyen esetekben valósul meg Haskellben?

Globális konstansok megosztása

Legyen three globális konstans:

three = 1 + 2

A futás közben az three első kiértékelése során kapott érték (a 3) eltárolódik a memóriában a további kiértékelések meggyorsítására.

Összetett példa

Az N alatt az M függvényt fogjuk többféle viselkedéssel implementálni.

Mindegyik változatban közös a Pascal háromszög következő sorának kiszámolása:

next :: [Integer] -> [Integer]
next l = [1] ++ zipWith (+) l (tail l) ++ [1]

Nincs megosztás

choose :: Int -> Int -> Integer
choose n m = pascalTriangle !! n !! m    where
    pascalTriangle :: [[Integer]]
    pascalTriangle = iterate next [1]

1500+1500 sor számolás:

test10 = (choose 1500 500, choose 1500 500) 

Teljes megosztás

chooseMemo :: Int -> Int -> Integer
chooseMemo n m = pascalTriangle !! n !! m
pascalTriangle :: [[Integer]]
pascalTriangle = iterate next [1]

1500+0 sor számolás:

test11 = (chooseMemo 1500 500, chooseMemo 1500 500) 

1000 sor megosztás

chooseMemo1000 :: Int -> Int -> Integer
chooseMemo1000 n m = pascalTriangle !! n !! m    where
    pascalTriangle :: [[Integer]]
    pascalTriangle = continue next (take 1000 pascalTriangle')
-- | Continue iteration
continue :: (a -> a) -> [a] -> [a]
continue f [x]    = iterate f x
continue f (x:xs) = x: continue f xs
pascalTriangle' :: [[Integer]]
pascalTriangle' = iterate next [1]

1000+500 + 0+500 sor számolás:

test12 = (chooseMemo1000 1500 500, chooseMemo1000 1500 500) 

Állítható megosztás

chooseMemoN :: Int -> (Int -> Int -> Integer)
chooseMemoN i = choose  where
    choose :: Int -> Int -> Integer
    choose n m = pascalTriangle !! n !! m   where
        pascalTriangle :: [[Integer]]
        pascalTriangle = continue next (take i pascalTriangle')
    pascalTriangle' :: [[Integer]]
    pascalTriangle' = iterate next [1]        

1000 + 500+500 sor számolás:

test13 = let f = chooseMemoN 1000 in (f 1500 500, f 1500 500) 

1000+500 + 1500+0 sor számolás:

test14 = (chooseMemoN 1000 1500 500, chooseMemoN 2000 1500 500) 

Állítható megosztás (másik)

chooseMemoMemoN :: Int -> (Int -> Int -> Integer)
chooseMemoMemoN i = choose  where
    choose :: Int -> Int -> Integer
    choose n m = pascalTriangle !! n !! m   where
        pascalTriangle :: [[Integer]]
        pascalTriangle = continue next (take i pascalTriangle'')
pascalTriangle'' :: [[Integer]]
pascalTriangle'' = iterate next [1]        

1000 + 500+500 sor számolás:

test15 = let f = chooseMemoMemoN 1000 in (f 1500 500, f 1500 500) 

1000+500 + 500+0 sor számolás:

test16 = (chooseMemoMemoN 1000 1500 500, chooseMemoMemoN 2000 1500 500) 

1500+0 + 0+500 sor számolás:

test17 = (chooseMemoMemoN 2000 1500 500, chooseMemoMemoN 1000 1500 500)