2009-07-07 5 views
6

Ho fatto la seguente funzione che è specifico per la monade IO:Haskell: IORef generico, 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 

Esempio Utilizzo:

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

stampe "hello" una volta.

Vorrei (un piccolo cruccio) farlo funzionare per il maggior numero di casi possibile (non solo in IO).

ho trovato stateref su hackage e con esso il mio codice è simile al seguente:

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

Esiste un'alternativa per stateref o un modo migliore per utilizzarlo di me?

+1

Sembra che tu stanno cercando di reinventare parte di http://sebfisch.github.com/explicit-sharing/? (Non male, vorrei solo chiarire). – ephemient

+0

Non penso che "perbacco" significhi cosa pensi che significhi. – ShreevatsaR

+0

@ephemient: conosco la condivisione esplicita. Ma a quanto ho capito, il mio codice dovrà essere eseguito all'interno del trasformatore di condivisione Monad, che non si adatta ai callback GLUT (I/O semplice) a meno che non lo faccia girare in un'altra discussione. – yairchu

risposta

6

Ho riscritto una piccola lezione di tipo MonadRef in alcune occasioni separate per uso personale e qualcuno probabilmente ne ha uno su Hackage, ma non riesco a trovarne uno che non sia ingombrato da altri bagagli.

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

allora è facile astrarre vostra routine Memoizzazione (anche se probabilmente si desidera sostituire IORef in questo contesto con una MVar.)

[Edit: chiarito verbage]

+0

Hackage ha implementazioni simili nei pacchetti "TypeCompose" e "ArrayRef" (trovati usando hayoo) – yairchu

+1

Er suppongo che l'auto-contenimento fosse il termine sbagliato, intendevo "senza un sacco di altri bagagli", quindi forse "libero da altri bagagli" 'sarebbe più appropriato. =) –

+0

comunque, credo che andrò con la generalizzazione solo se il bisogno si pone effettivamente .. :) – yairchu

Problemi correlati