【问题标题】:haskell global varhaskell 全局变量
【发布时间】:2016-01-10 17:59:18
【问题描述】:

任务是创建动态链接库,它封装了数据库的辛勤工作。由于一些设计限制,我有一个定义的接口,其中包含许多功能。每个函数都接受一个参数并在数据库查询中使用它们。数据库连接应该在 dll 中,应用程序不想打扰是否有任何连接。

初始化数据库连接然后将其提供给每个函数而不显式传递它的最佳方法是什么。

当然,总的来说,我想使用 State monad。但 dll 并非设计为只有一个入口点。

【问题讨论】:

  • 我不确定您所说的“没有提供 dll 以拥有一个入口点”是什么意思。请问可以展开吗?使用 monad 来处理这些事情通常更健壮、更好。
  • 应该提供几个独立的功能。其中两个initclose,其他是数据获取者和数据库更新者。并且所有函数都不应该直接处理数据库处理程序。

标签: haskell global-variables


【解决方案1】:

听起来您正在尝试创建一个可以从其他语言调用的 DLL。如果是这样,那么您的所有功能都将存在于 IO monad 中。所以你可以使用 IORef 来存储数据库连接对象。

已更新(参见下面的 cmets)

GHC 与全局随机数生成器状态有类似的问题。以下是 System.Random 的相关源代码:

-- |Gets the global random number generator.
getStdGen :: IO StdGen
getStdGen  = readIORef theStdGen

theStdGen :: IORef StdGen
theStdGen  = unsafePerformIO $ do
   rng <- mkStdRNG 0
   newIORef rng

所以大概类似的东西适用于数据库连接。是的,这是在使用邪恶的 unsafePerformIO,但有时你必须是邪恶的。

【讨论】:

  • @Paul Johnson:如果他正在设计自己的界面,他的函数可以有一个会话参数来保存这个IORef。问题是他需要实现一个特定的 API,而他不能将 IORef 提供给函数,因此他需要某种方式来共享全局 IORef
  • @Pail Jounson:确认。你的答案很好,一切都会从入口点调用。
【解决方案2】:

您可以使用unsafePerformIO“作弊”:

{-# NOINLINE globalVar #-}
globalVar :: MVar Integer
globalVar = unsafePerformIO (newMVar 17)

我对固定 API 表示哀悼。

【讨论】:

猜你喜欢
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 2015-06-12
  • 2019-07-24
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多