Translation of imperative memoization code in Haskell

Memory is a useful thing, and since it is strongly associated with functions, I would suggest that Haskell has the right technique for implementing it, at least quite simply.

var memo = function (f) {
    var cache = {};
    return function (x) {
        if (cache[x]) return cache[x];
        else return cache[x] = f(x);
    }
}

//Usage:
var fib = memo(function (x) {
    if (x == 0) return 1;
    if (x == 1) return 1;
    return fib(x - 1) + fib(x - 2);
});

fib(100);

This is the code I wrote in JavaScript that does what I want. What would be a good translation to Haskell that can offer similar usability and performance?

To reduce the ambiguity of the question, I'm not interested in replicating the generality of the JS solution, because Haskell is strongly typed. Something with a signature type

memo :: (Int -> b) -> (Int -> b)

which can be manually extended for several parameters, and perhaps even different types will be in order.

+4
source share
1

, JavaScript, - ; hashmaps ( , ).

Haskell. - , , memoisation: -. ?

, , . Int -> - :

memoInt :: (Int -> b) -> Int -> b
memoInt f = look
 where positives = [ f x | x <- [0..] ]
       negatives = [ f x | x <- [-1, -2 ..] ]
       look x | x<0        = negatives !! (1-x)
              | otherwise  = positives !! x

, - |x|.

, , O (√n) O (n):

memoInt' :: (Int -> b) -> Int -> b
memoInt' f = look
 where table = [ [ f (sqrtX^2 + dx) | dx <- [0..]    ]
                                    | sqrtX <- [0..] ]
       look x | x<0        = negDomain x
              | otherwise  = let sqrtX = floor . sqrt $ fromIntegral x
                             in table !! sqrtX !! (max 0 $ x - sqrtX)
       negDomain = memoInt' (f . negate)

( - , sqrt)

+9

Source: https://habr.com/ru/post/1534472/


All Articles