2009-07-07 8 views
6

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やそれより良い方法を使用する方法がありますか?

+1

それはあなたのように見えますhttp://sebfisch.github.com/explicit-sharing/の一部を再発明しようとしていますか? (悪いことではないが、私は明確にしたい) – ephemient

+0

"ピーボー"とは、あなたが意味すると思うことを意味するとは思わない。 – ShreevatsaR

+0

@ephemient:明示的共有について知っています。しかし、私が理解しているように、私のコードが別のスレッドで実行されない限り、GLUTコールバック(プレーンIO)に適合しない共有モナドトランスの内部で実行する必要があります。 – yairchu

答えて

6

私は自分の個人的な使用のためにちょっとした別の機会にちょっとしたMonadRefクラスを書き直しました。誰かがおそらくHackageを持っていますが、他の手荷物に妨げられないものは見つけられません。

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 
    ... 

(おそらくMVarで、この文脈でIORefを交換したいのに。)そして、それは離れてあなたのメモ化ルーチン抽象的に簡単である

[編集:明確verbage]

+0

Hackageは "TypeCompose"パッケージと "ArrayRef"パッケージ(hayooで見つけたもの)の同様の実装を持っています – yairchu

+1

私は自己完結型の用語が間違った用語だったと思います。 'より適切であろう。 =) –

+0

とにかく、実際に必要が生じた場合にのみ一般化するつもりです:) – yairchu