Vasiliy Stavenko
Vasiliy Stavenko

Reputation: 1214

haskell global var

The task is to create dynamically linked library, which encapsulates database hard work. Due to some design limitations I have a defined interface, which consist of numerous functions. Each function takes a parameters and use them in database query. Database connection should be inside dll and application don't want to bother is there any connection.

What is the best way to initialize db connection and then give it to every function without passing it around explicitly.

Of course in general I'd like to use State monad. But dll is not designed to have one entry point.

Upvotes: 4

Views: 1066

Answers (2)

yairchu
yairchu

Reputation: 24814

You can "cheat" using unsafePerformIO:

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

My condolences for the fixed API.

Upvotes: 1

Paul Johnson
Paul Johnson

Reputation: 17806

It sounds like you are trying to create a DLL that can be called from other languages. If so then all your functions will live in the IO monad. So you can use an IORef to store the database connection object.

Updated (see comments below)

GHC has a similar problem with the global random number generator state. Here is the relevant source code from 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

So presumably something similar would work for the DB connection. Yes, this is using the evil unsafePerformIO, but sometimes you just gotta be evil.

Upvotes: 2

Related Questions