{-# LANGUAGE GADTs #-} module Data.MultiIORef ( MultiIORef(..) , loosenIORef , makeMultiIORef , zoomMultiIORef , newMultiIORef , readMultiIORef , readMultiIORefList , readMultiIORefHead , modifyMultiIORef, modifyMultiIORef' , writeMultiIORef ) where import Data.IORef.Zoom import Control.Lens data MultiIORef a where MultiIORef :: IORef x -> ATraversal' x a -> MultiIORef a loosenIORef :: IORef a -> MultiIORef a loosenIORef v = MultiIORef v id makeMultiIORef :: ATraversal' x a -> IORef x -> MultiIORef a makeMultiIORef = flip MultiIORef zoomMultiIORef :: ATraversal' a b -> MultiIORef a -> MultiIORef b zoomMultiIORef t1 (MultiIORef v t2) = MultiIORef v . confusing $ cloneTraversal t2 . cloneTraversal t1 newMultiIORef :: a -> IO (MultiIORef a) newMultiIORef a = MultiIORef <$> newIORef a <*> pure id readMultiIORef :: Monoid a => MultiIORef a -> IO a readMultiIORef (MultiIORef v t) = (^. cloneTraversal t) <$> readIORef v readMultiIORefList :: MultiIORef a -> IO [a] readMultiIORefList (MultiIORef v t) = (^.. cloneTraversal t) <$> readIORef v readMultiIORefHead :: MultiIORef a -> IO (Maybe a) readMultiIORefHead (MultiIORef v t) = (^? cloneTraversal t) <$> readIORef v modifyMultiIORef :: MultiIORef a -> (a -> a) -> IO () modifyMultiIORef (MultiIORef v t) f = modifyIORef v $ cloneTraversal t %~ f modifyMultiIORef' :: MultiIORef a -> (a -> a) -> IO () modifyMultiIORef' (MultiIORef v t) f = modifyIORef' v $ cloneTraversal t %~ f writeMultiIORef :: MultiIORef a -> a -> IO () writeMultiIORef (MultiIORef v t) a = modifyIORef' v $ cloneTraversal t .~ a