我正在尝试学习Haskell,并且正在与Ioref一起玩,我尝试保存并查找记录。我的代码看起来像这样(请注意,在此示例中,我选择"字符串"为IOREF类型,仅用于说明和短暂性,在我的实际代码中,我正在使用记录。也忽略我正在使用集合在地图上,我将更改):
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"
我要实现的是在两个函数调用之间共享状态(集合),以便findStringInState
可以返回我刚刚插入集合中的String
。但是当我运行doStuff
功能时,我会得到:
*MyTest> doStuff
### saved: fromList ["string1"]
Looking for string1 in: fromList []
Nothing
我可能误解了一些东西,因为我认为IOREF确实应该是我州的容器。
- 为什么这不起作用?
- 我该怎么做才能使它起作用?
似乎您将 IO IORefState
与 IORefState
(无IO
)混淆了,更普遍地, IO a
与 a
。
在您的情况下, IO IORefState
的值是 newIORef empty
,它代表"从头开始创建新的新IORef
的动作"。
相比之下, IORefState
(无IO
)是正确的, raw对象您应该在使用它的功能中共享(saveStringToState
和findStringInState
)。
然后,saveStringToState
和findStringInState
单独调用newIORef empty
,即它们都创建一个不同的IORefState
对象,该对象不能受到另一个对象。
要修复,您必须在doStuff
中调用newIORef empty
(使用<-
的IO
操作),并共享由newIORef empty
而不是IO IORefState
创建的IORefState
:
saveStringToState :: IORefState -> String -> IO String
...
findStringInState :: IORefState -> String -> IO (Maybe String)
...
let stateIO = newIORef empty
in do ioRef <- stateIO
saveStringToState ioRef "string1"
findStringInState ioRef "string1"
-- Or, more simply:
do ioRef <- newIORef empty
saveStringToState ioRef "string1"
findStringInState ioRef "string1"
我认为,使用a
的IO a
之间的差异类似于"返回为a
键入值的函数对象(具有副作用)(具有某些副作用)"one_answers"仅在另一个中键入a
的原始值"之间的差异。编程语言。