Haskell global var

The task is to create a dynamically linked library that encapsulates the work with the database. Due to some design limitations, I have a specific interface that consists of many functions. Each function takes parameters and uses them in a database query. The database connection must be inside the dll, and the application does not want to worry about having any connection.

What is the best way to initialize a db connection and then pass it to each function without passing it explicitly.

Of course, in general, I would like to use the state monad. But the dll is not designed for one entry point.

+4
source share
2 answers

You can cheat using unsafePerformIO :

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

My condolences for the fixed API.

+1
source

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

Updated (see comments below)

GHC has a similar problem with the state of the global random number generator. Here is the corresponding 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 

Thus, presumably something like this will work to connect to the database. Yes, this is the use of evil unsafePerformIO, but sometimes you just have to be evil.

+2
source

All Articles