2009-07-07 23 views
6

tôi đã thực hiện các chức năng sau đó là cụ thể cho các đơn nguyên IO:Haskell: IORef chung, 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 

Ví dụ sử dụng:

main :: IO() 
main = do 
    p <- memoIO $ putStrLn "hello" 
    p 
    p 

In "hello" một lần.

Tôi muốn (một chú chó cưng) để làm cho nó hoạt động trong nhiều trường hợp nhất có thể (không chỉ trong IO).

tôi thấy stateref trên hackage và cùng với nó mã của tôi trông như thế này:

{-# 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 

Có một sự thay thế cho stateref hoặc một cách tốt hơn để sử dụng nó hơn tôi đã làm?

+1

Dường như bạn đang cố gắng phát minh lại một phần của http://sebfisch.github.com/explicit-sharing/? (Không phải là một điều xấu, tôi chỉ muốn làm rõ.) – ephemient

+0

Tôi không nghĩ rằng "peeve" có nghĩa là những gì bạn nghĩ rằng nó có nghĩa là. – ShreevatsaR

+0

@ephemient: Tôi biết về chia sẻ rõ ràng. Nhưng như tôi hiểu nó sẽ yêu cầu mã của tôi để chạy bên trong biến áp monad chia sẻ, mà sẽ không phù hợp với callback GLUT (đồng bằng IO), trừ khi tôi làm cho nó chạy trong thread khác. – yairchu

Trả lời

6

Tôi đã viết lại một ít cheesy ít MonadRef lớp vào một vài dịp riêng biệt cho mục đích cá nhân của riêng tôi và ai đó có thể có trên Hackage, nhưng tôi không thể tìm thấy một trong đó là không bị cản trở với hành lý khác.

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

Sau đó, nó rất dễ dàng để tóm tắt đi thói quen memoization của bạn (mặc dù bạn có thể muốn thay thế IORef trong bối cảnh này với một MVar.)

[Edit: làm rõ verbage]

+0

Hackage có các triển khai tương tự trong các gói "TypeCompose" và "ArrayRef" (được tìm thấy bằng cách sử dụng hayoo) – yairchu

+1

Er Tôi cho rằng tự chứa là sai cụm từ, có nghĩa là 'không có hành lý khác', vì vậy có lẽ 'không bị cản trở với hành lý khác 'sẽ thích hợp hơn. =) –

+0

dù sao đi nữa, tôi đoán tôi sẽ đi với khái quát hóa nó chỉ khi nhu cầu thực sự phát sinh .. :) – yairchu

Các vấn đề liên quan