6

IO モナドに固有の次の関数を作成しました。

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" を 1 回出力します。

(IOだけでなく)できるだけ多くのケースで機能するようにしたいと思います(ペットピーブ)。

ハックで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 の代替手段や、私が行ったよりも良い使用方法はありますか?

4

1 に答える 1

7

私はMonadRef自分の個人的な使用のためにいくつかの別々の機会に安っぽい小さなクラスを書き直しました、そして誰かがおそらくハッキングにそれを持っています、しかし私は他の荷物に邪魔されていないものを見つけることができません。

class Monad m => MonadRef m where
    type Ref m :: * -> *
    newRef :: a -> Ref m a
    writeRef :: Ref m a -> -> m ()
    readRef :: Ref m a -> m a

instance MonadRef IO where
    type Ref IO = IORef
    newRef = newIORef
    writeRef = writeIORef
    readRef = writeIORef

instance MonadRef STM where
    type Ref STM = TVar
    ...


instance MonadRef (ST s) where
    type Ref (ST s) = STRef s
    ...

IORefそうすれば、メモ化ルーチンを簡単に抽象化できます(ただし、このコンテキストではおそらく。に置き換えたいと思うでしょうMVar)。

[編集:明確な言葉遣い]

于 2009-07-07T15:51:46.370 に答える