Haskell 哈斯克尔:回忆录
我试图重新学习哈斯凯尔,在离开多年后,我忘记了一切,我发现自己仍然对我的记忆感到困惑。特别是,我正试图编写一个程序来生成Haskell 哈斯克尔:回忆录,haskell,recursion,memoization,Haskell,Recursion,Memoization,我试图重新学习哈斯凯尔,在离开多年后,我忘记了一切,我发现自己仍然对我的记忆感到困惑。特别是,我正试图编写一个程序来生成D[n]对象的混乱数量n对象(原始位置没有项目的排列);数字D[n]可以通过D[1]=0,D[2]=1,D[n]=(n-1)(D[n-1]+D[n-2])递归定义 所以这是可行的: der :: Int -> Integer der n = lder !! n where lder = 1 : 0 : zipWith3 (\n d1 d2 -> n * (d1+
D[n]
对象的混乱数量n
对象(原始位置没有项目的排列);数字D[n]
可以通过D[1]=0
,D[2]=1
,D[n]=(n-1)(D[n-1]+D[n-2])递归定义
所以这是可行的:
der :: Int -> Integer
der n = lder !! n
where lder = 1 : 0 : zipWith3 (\n d1 d2 -> n * (d1+d2)) [1..] lder (tail lder)
与此类似(这有点笨拙,因为它需要三个功能):
您会发现最后一个是标准记忆斐波那契数函数的副本。我的函数可以工作,但没有被记忆,因为它挂起的值大于30。此外,如果我将此函数编写为仅对大于或等于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)
这根本不起作用。我很想知道最后两个函数有什么问题。
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)
映射der[0..]
部分将针对NDS
的任何应用程序重新计算,特别是包括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)
这是一个范围问题。请尝试使用nds=(map der[0..!!)
,这表示计算map
时不需要知道n
(编译器不自动执行此操作的原因是它可能会创建不需要的内存泄漏..这就是您在这里所做的,只是您想要内存泄漏;-)非常感谢!是的,这很好用。这些都是我还没有弄清楚的棘手问题。奇怪的是,地图需要在[0..]
上定义;如果我在[1..]
上定义它,函数就不起作用了。是的,那是因为代码>以零为基础。该策略取决于以下事实:[0..]!!n=n
对于我们感兴趣的所有n
s(因为我们需要map f[0..!!n=fn
,所以它最好适用于f=id
)
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)
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)