2009-12-09 64 views
4

任务是创建动态链接库,它封装了数据库的辛勤工作。由于一些设计上的限制,我有一个定义好的界面,它由许多功能组成。每个函数都接受一个参数并在数据库查询中使用它们。数据库连接应该在DLL里面,应用程序不想打扰有没有连接。haskell global var

什么是最好的方式来初始化数据库连接,然后把它给每个函数,而不明确传递它。

当然,一般来说我想使用状态monad。但是dll的设计并不是有一个入口点。

+1

我不确定你的意思是“dll没有提供一个入口点”。你能否扩大?使用monad来处理这些事情通常更健壮和更好。 – svenningsson 2009-12-09 12:09:19

+0

应该提供几个独立的功能。其中两个'init'&'close', 其他的是数据获取器和数据库更新器。 并且所有函数都不应该直接处理数据库处理程序。 – 2009-12-09 23:46:29

回答

1

可以 “欺骗” 使用unsafePerformIO

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

我对固定API慰问。

+1

没有NOINLINE,这很危险 - 请参阅http://neilmitchell.blogspot.ch/2014/10/hlint-now-spots-bad-unsafeperformio.html。 – ron 2016-01-08 15:49:36

+0

@ron:谢谢。固定 – yairchu 2016-01-10 09:59:30

2

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

更新(见下面的评论)

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 

所以大概类似的东西会为DB连接工作。是的,这是使用邪恶不安全的PERFORMIO,但有时你只是邪恶。

+0

@Paul Johnson:如果他设计自己的界面,他可以为他的函数拥有一个会话参数来保存这个'IORef'。问题在于他需要实施特定的API,因为他不能将IORef授予职能,所以他需要某种方式来共享全球IORef – yairchu 2009-12-10 14:33:38

+0

@Paul Jounson:确认。你的回答是好的,是从入口点召唤一切。 – 2009-12-10 21:31:53