Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法在Haskell中记忆一个值?_Haskell_Functional Programming_Memoization - Fatal编程技术网

有没有办法在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 -

我在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 ! 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使用读卡器单子的回答,这与我向你展示的相同(使用状态单子而不做任何修改-所以我也应该想到
读卡器
).这个问题似乎是为了向读者宣传莫纳德。回答得好。