gpt4 book ai didi

haskell - 内存和重复 IO monad

转载 作者:行者123 更新时间:2023-12-04 19:02:40 25 4
gpt4 key购买 nike

2015-11-29 编辑 : 见底部

我正在尝试编写一个具有最后一次操作按钮的应用程序。有问题的命令可以要求输入,我对如何实现这一点的想法是使用内存 IO 重新运行生成的 monad。

SO上有很多类似问题的帖子,但似乎没有一个解决方案在这里有效。

我解除了memoIO来自 this SO answer 的代码,并将实现更改为运行 MonadIO .

-- Memoize an IO function
memoIO :: MonadIO m => m a -> m (m a)
memoIO action = do
ref <- liftIO $ newMVar Nothing
return $ do
x <- maybe action return =<< liftIO (takeMVar ref)
liftIO . putMVar ref $ Just x
return x

我对我的应用程序的方法有一个小的复制,唯一真正的区别是我的应用程序有一个大的转换器堆栈,而不是仅仅在 IO 中运行:
-- Global variable to contain the action we want to repeat
actionToRepeat :: IORef (IO String)
actionToRepeat = unsafePerformIO . newIORef $ return ""

-- Run an action and store it as the action to repeat
repeatable :: IO String -> IO String
repeatable action = do
writeIORef actionToRepeat action
action

-- Run the last action stored by repeatable
doRepeat :: IO String
doRepeat = do
x <- readIORef actionToRepeat
x

我的想法是我可以用内存 IO 存储一个 Action 在 IORef (通过 repeatable )当我记录最后完成的事情时,然后用 doRepeat 再次执行它.

我通过以下方式测试:
-- IO function to memoize
getName :: IO String
getName = do
putStr "name> "
getLine

main :: IO ()
main = do
repeatable $ do
memoized <- memoIO getName
name <- memoized
putStr "hello "
putStrLn name
return name
doRepeat
return ()

预期输出:
name> isovector
hello isovector
hello isovector

但实际输出:
name> isovector
hello isovector
name> wasnt memoized
hello wasnt memoized

我不完全确定问题是什么,甚至不知道如何进行调试。枪击我的头,我认为懒惰的评估在某个地方咬了我,但我不知道在哪里。

提前致谢!

编辑 2015-11-29 : 我的预期用例是实现 repeat last change vim 克隆中的运算符。每个 Action 都可以执行任意数量的任意 IO 调用,我希望它能够指定哪些应该被内存(读取文件,可能不是。询问用户输入,是的)。

最佳答案

问题主要在于您每次调用操作时都会创建一个新备忘录

你需要搬家memoized <- memoIO getName高于行动

main :: IO ()
main = do
memoized <- memoIO getName --moved above repeatable $ do
repeatable $ do
--it was here
name <- memoized
putStr "hello "
putStrLn name
return name
doRepeat
return ()

编辑:这是可以接受的吗
import Data.IORef
import System.IO.Unsafe

{-# NOINLINE actionToRepeat #-}
actionToRepeat :: IORef (IO String)
actionToRepeat = unsafePerformIO . newIORef $ return ""

type Repeatable a = IO (IO a)

-- Run an action and store the Repeatable part of the action
repeatable :: Repeatable String -> IO String
repeatable action = do
repeatAction <- action
writeIORef actionToRepeat repeatAction
repeatAction

-- Run the last action stored by repeatable
doRepeat :: IO String
doRepeat = do
x <- readIORef actionToRepeat
x

-- everything before (return $ do) is run just once
hello :: Repeatable String
hello = do
putStr "name> "
name <- getLine
return $ do
putStr "hello "
putStrLn name
return name

main :: IO ()
main = do
repeatable hello
doRepeat
return ()

关于haskell - 内存和重复 IO monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33980196/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com