有没有办法在Haskell中记忆一个值?
我在Haskell中具有以下功能:有没有办法在Haskell中记忆一个值?,haskell,functional-programming,memoization,Haskell,Functional Programming,Memoization,我在Haskell中具有以下功能: memdb = -- load the contents of a database into memory as a Map 然后我有以下几行: map (\x -> memdb ! x) values 我希望memdb只生成一次Map,而不是每次迭代Map。我可以这样做: make_memdb = -- equivalent to memdb in previous example memdb <- make_memdb map (\x -
memdb = -- load the contents of a database into memory as a Map
然后我有以下几行:
map (\x -> memdb ! x) values
我希望memdb只生成一次Map,而不是每次迭代Map
。我可以这样做:
make_memdb = -- equivalent to memdb in previous example
memdb <- make_memdb
map (\x -> memdb ! x) values
make_memdb=--等同于前面示例中的memdb
memdb memdb!x) 价值观
但这意味着我必须将memdb
传递给使用它的每个函数。我有没有办法:
a。避免每次调用或重新计算memdb
b。将在
make_memdb
中生成的值保存为常量,这样我就可以避免将其传递给使用它的每个函数?另请参见。您似乎希望通过IO
获取memdb
,以避免传递更多参数,对吗?然后,您询问是否可以(A)定义memdb
,这意味着它将是一个顶级函数,而不需要从DB加载数据,或者(B)是否可以使用全局范围保存加载的数据结构
使用IORef
和unsafePerformIO
来定义顶级可变全局变量,这两种方法都是可行的。我不建议你这样做。重构既笨拙又烦人。也就是说,我将向您展示如何:
假设您有一个函数:
make_memdb :: IO (Map K V)
您可以声明顶级可变变量:
import Data.Map as M
import Data.IORef
mRef :: IORef (Map K V)
mRef = unsafePerformIO $ newIORef M.empty
{-# NOINLINE mRef #-}
main = do
m <- make_memdb
writeIORef mRef m
... do stuff using mRef ...
stuffUsingMRef ... = do
memdb <- readIORef
let vs = map (memdb !) values
return vs
导入数据。映射为M
导入数据.IORef
mRef::IORef(映射K V)
mRef=unsafePerformIO$newIORef M.empty
{-#NOINLINE mRef}
main=do
m由于映射来自数据库,这意味着它不能是常量,因为在应用程序运行期间它可能会有所不同
但这意味着我必须将memdb传递给每个使用它的函数
是的,但是有一些工具可以让事情变得不像听起来那么糟糕。特别是,这听起来像是一个完美的用例
读卡器单子通常在您有一些值(如配置)时使用,您希望在程序开始时加载这些值,然后能够在程序中访问它,而不必一直显式地传递它。下面是一个简短的示例,说明如何使用它:
main = do
memdb <- make_memdb -- Get the memdb from the database once and for all
runReaderT foo memdb
foo = do
memdb <- ask -- Grab the memdb. Will not reload from the database
liftIO $ putStrLn "Hello, world" -- IO actions have to be lifted
-- [...]
main=do
memdb@Craig Stuntz的可能副本:在发布我的问题之前,我已经通读了这个问题。这些答案将如何帮助我实现a。还是b@克雷格:尽管有这个题目,但这个问题并不是通常意义上的记忆化问题。这不是这个问题的重复。你能给我一个关于状态单子有什么帮助的例子吗?请看hammer使用读卡器单子的回答,这与我向你展示的相同(使用状态单子而不做任何修改-所以我也应该想到读卡器).这个问题似乎是为了向读者宣传莫纳德。回答得好。