IOモナドに固有の次の関数を作った:ハスケル:ジェネリックIORef、MVar?
memoIO :: MonadIO m => m a -> IO (m a)
memoIO action = do
ref <- newMVar Nothing
return $ do
x <- maybe action return =<< liftIO (takeMVar ref)
liftIO . putMVar ref $ Just x
return x
使用例:
main :: IO()
main = do
p <- memoIO $ putStrLn "hello"
p
p
"hello
"を一度プリントします。
私は(ペットのピーボー)は、IOだけでなく、できるだけ多くのケースで動作させることを望みます。
hackageにstaterefが見つかりました。これで私のコードは次のようになりました:
{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, Rank2Types, UndecidableInstances #-}
import Data.MRef
class (NewMRef r m a, DefaultMRef r m a, PutMRef r m a, TakeMRef r m a) => MRef r m a
instance (NewMRef r m a, DefaultMRef r m a, PutMRef r m a, TakeMRef r m a) => MRef r m a
memo :: (MRef r m (Maybe a), Monad s) => (forall x. m x -> s x) -> s a -> m (s a)
memo liftFunc action = do
ref <- newDefaultMRef Nothing
return $ do
x <- maybe action return =<< liftFunc (takeDefaultMRef ref)
liftFunc . putDefaultMRef ref $ Just x
return x
代わりにstaterefやそれより良い方法を使用する方法がありますか?
それはあなたのように見えますhttp://sebfisch.github.com/explicit-sharing/の一部を再発明しようとしていますか? (悪いことではないが、私は明確にしたい) – ephemient
"ピーボー"とは、あなたが意味すると思うことを意味するとは思わない。 – ShreevatsaR
@ephemient:明示的共有について知っています。しかし、私が理解しているように、私のコードが別のスレッドで実行されない限り、GLUTコールバック(プレーンIO)に適合しない共有モナドトランスの内部で実行する必要があります。 – yairchu