haskell 交换两个IORef的值

pbgvytdp  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(139)

我需要这个功能:

x <- newIORef "x"
y <- newIORef "y"
swapIORefs x y
readIORef x -- Outputs "y"
readIORef y -- Outputs "x"

我最好的尝试是:

swapIORefs :: IORef a -> IORef a -> IO ()
swapIORefs x y = do let xvalue = readIORef x
                    let yvalue = readIORef y
                    writeIORef x yvalue
                    writeIORef y xvalue

贝瑟给了我:

The last statement in a 'do' block must be an expression
      let yvalue = readIORef y writeIORef x yvalue writeIORef y xvalue
   |
51 |                     let yvalue = readIORef y
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^...
kd3sttzy

kd3sttzy1#

这似乎是工作:

swapIORefs :: IORef a -> IORef a -> IO ()
swapIORefs x y = do xvalue <- readIORef x
                    yvalue <- readIORef y
                    writeIORef x yvalue
                    writeIORef y xvalue

readIORef的类型为IORef a -> IO a,而writeIORef的类型为IORef a -> a -> IO (),因此为了写入值,您需要从IO中“获取”值,您可以使用<-绑定来完成此操作。
OP中的let绑定会将xvalue绑定到IO a,而这不会对writeIORef进行类型检查。
GHCi:

ghci> x <- newIORef "x"
ghci> y <- newIORef "y"
ghci> swapIORefs x y
ghci> readIORef x
"y"
ghci> readIORef y
"x"
z9zf31ra

z9zf31ra2#

稍微短一点,虽然只是语法上的:

swapIORefs :: IORef a -> IORef a -> IO ()
swapIORefs x y = (readIORef x <* (readIORef y >>= writeIORef x)) >>= writeIORef y

这相当于@ MarkSeemann的代码,但使用了一些函数,如>>=<*,将值隐式传递给下一个引用。

相关问题