I'm trying to learn Haskell and I'm playing around with IORef to which I try to save and find records. My code looks something like this (note that I've chosen "String" as IORef type in this example only for convienence and briefty, in my actual code I'm using a record. And also ignore that I'm using a Set instead of a Map, I will change that):
module MyTest where
import Data.IORef
import Data.Set
import Data.Foldable (find)
type State = (Set String)
type IORefState = IORef State
saveStringToState :: IO IORefState -> String -> IO String
saveStringToState stateIO string = do
state <- stateIO
atomicModifyIORef
state
(\oldStrings ->
let updatedStrings = insert string oldStrings
in (updatedStrings, updatedStrings))
stringsState <- readIORef state :: IO State
putStrLn ("### saved: " ++ show stringsState)
return string
findStringInState :: IO IORefState -> String -> IO (Maybe String)
findStringInState stateIO soughtString = do
state <- stateIO :: IO IORefState
strings <- readIORef state :: IO State
putStrLn ("Looking for " ++ soughtString ++ " in: " ++ show strings)
return $ find (== soughtString) strings
doStuff =
let stateIO = newIORef empty
in do saveStringToState stateIO "string1"
findStringInState stateIO "string1"
What I want to achieve is to share the state (Set) between the two function calls so that findStringInState
can return the String
that I just inserted into the Set. But when I run the doStuff
function I get this:
*MyTest> doStuff
### saved: fromList ["string1"]
Looking for string1 in: fromList []
Nothing
I've probably misunderstood something since I thought the IORef should indeed be the container for my state.
- Why is this not working?
- What can I do to make it work?