Haskell: memoization

I try to relearn Haskell after many years and forget about everything, and I still embarrass my memory. In particular, I am trying to write a program to generate the number of violations of D[n]objects n(permutations without an element in the original place); numbers D[n]can be defined recursively D[1]=0, D[2]=1, D[n]=(n-1)(D[n-1]+D[n-2]).

So this works:

der :: Int -> Integer
der n = lder !! n
  where lder = 1 : 0 : zipWith3 (\n d1 d2 -> n * (d1+d2)) [1..] lder (tail lder)

like this (which is a bit awkward, as it requires three functions):

nder :: Int -> Integer
nder n = nderTab !! n

nderTab :: [Integer]
nderTab = [nderCalc n | n <- [0..]]

nderCalc :: Int -> Integer
nderCalc n
  | n == 0    = toInteger 1
  | n == 1    = toInteger 0
  | otherwise = toInteger (n-1) * (nder (n-1) + nder (n-2))

But this is not so:

nders :: Int -> Integer
nders n = (map der [0 ..]) !! n
  where der 0 = 1
        der 1 = 0
        der n = (nders (n-2) + nders (n-1)) * toInteger (n-1)

You will recognize this last as a copy of the standard memoized Fibonacci number function. My function works, but is not remembered, because it freezes at values ​​exceeding about 30. In addition, if I write this function to work only with values ​​greater than or equal to 1:

nders :: Int -> Integer
nders n = (map der [1 ..]) !! n
  where der 1 = 0
        der 2 = 1
        der n = (nders (n-2) + nders (n-1)) * toInteger (n-1)

. , .

+1
1

nders :: Int -> Integer
nders n = (map der [0 ..]) !! n
  where der 0 = 1
        der 1 = 0
        der n = (nders (n-2) + nders (n-1)) * toInteger (n-1)

map der [0..] nders, der.

, () n, :

nders :: Int -> Integer
nders = (memoized !!)
  where 
    memoized = map der [0 ..]

    der 0 = 1
    der 1 = 0
    der n = (nders (n-2) + nders (n-1)) * toInteger (n-1)
+2

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


All Articles