Advertisement
Guest User

Untitled

a guest
Oct 26th, 2016
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.86 KB | None | 0 0
  1. {-# LANGUAGE RecordWildCards, ScopedTypeVariables #-}
  2. import Data.Set
  3. import Data.IORef
  4. import Data.Maybe
  5. import Data.Dynamic hiding (cast)
  6. import Data.Function(on)
  7. import Control.Applicative
  8. import System.IO.Unsafe
  9.  
  10. data Thunk = Thunk
  11. { result :: IORef (Maybe Dynamic)
  12. , sub :: IORef (Set Thunk)
  13. , super :: IORef (Set Thunk)
  14. , thunk :: IO Dynamic
  15. , ident :: Int
  16. }
  17.  
  18. instance Eq Thunk where
  19. (==) = (==) `on` ident
  20.  
  21. instance Ord Thunk where
  22. compare = compare `on` ident
  23.  
  24. instance Show Thunk where
  25. show (Thunk{..}) = "Thunk { ident = " ++ show ident ++ ", result = " ++ (show . unsafePerformIO . readIORef $ result) ++ "}"
  26.  
  27. {-# NOINLINE counter #-}
  28. counter :: IORef Int
  29. counter = unsafePerformIO $ newIORef 0
  30.  
  31. athunk :: IO Dynamic -> IO Thunk
  32. athunk thunk = do
  33. ident <- atomicModifyIORef counter (\c -> (c+1,c))
  34. result <- newIORef Nothing
  35. sub <- newIORef mempty
  36. super <- newIORef mempty
  37. return Thunk {..}
  38.  
  39. add :: Thunk -> Thunk -> IO ()
  40. add sp sb = do
  41. modifyIORef (sub sp) (insert sb)
  42. modifyIORef (super sb) (insert sp)
  43.  
  44. remove :: Thunk -> Thunk -> IO ()
  45. remove sp sb = do
  46. modifyIORef (sub sp) (delete sb)
  47. modifyIORef (super sp) (delete sp)
  48.  
  49. compute :: Thunk -> IO Dynamic
  50. compute a@Thunk{..} = do
  51. r <- readIORef result
  52. case r of
  53. Just r -> return r
  54. Nothing -> do
  55. mapM_ (remove a) <$> readIORef sub
  56. v <- thunk
  57. writeIORef result (Just v)
  58. return v
  59.  
  60. dirty :: Thunk -> IO()
  61. dirty (a@Thunk{..}) = do
  62. writeIORef result Nothing
  63. mapM_ dirty =<< readIORef super
  64.  
  65. aref :: Dynamic -> IO Thunk
  66. aref val = do
  67. ident <- atomicModifyIORef counter (\c -> (c+1,c))
  68. result <- newIORef (Just val)
  69. sub <- newIORef mempty
  70. super <- newIORef mempty
  71. return Thunk { thunk = fromJust <$> readIORef result, ..}
  72.  
  73. set :: Thunk -> Maybe Dynamic -> IO ()
  74. set (a@Thunk{..}) val = do
  75. dirty a
  76. writeIORef result val
  77.  
  78. {-# NOINLINE adapting #-}
  79. adapting :: IORef (Maybe Thunk)
  80. adapting = unsafePerformIO $ newIORef Nothing
  81.  
  82. force :: Thunk -> IO Dynamic
  83. force a@Thunk{..} = do
  84. prev <- readIORef adapting
  85. writeIORef adapting (Just a)
  86. result <- compute a
  87. writeIORef adapting prev
  88. case prev of
  89. Nothing -> return ()
  90. Just ad -> add ad a
  91. return result
  92.  
  93. adapt = athunk
  94.  
  95. memoize :: (Eq a) => (a -> IO b) -> IO (a -> IO b)
  96. memoize f = do
  97. s <- newIORef []
  98. return $ \(x :: a) -> do
  99. v <- lookup x <$> readIORef s
  100. case v of
  101. Just v' -> return v'
  102. Nothing -> do
  103. r <- f x
  104. modifyIORef s ((x,r):)
  105. return r
  106.  
  107. amemoize_l :: Eq a => (a -> IO Dynamic) -> IO (a -> IO Thunk)
  108. amemoize_l f = memoize (\x -> adapt (f x))
  109.  
  110. amemoize :: Eq a => (a -> IO Dynamic) -> IO (a -> IO Dynamic)
  111. amemoize f = do
  112. f' <- amemoize_l f
  113. return $ \x -> f' x >>= force
  114.  
  115. cast :: Typeable a => Dynamic -> a
  116. cast x = let a = fromDyn x (error $ "Bad cast to " ++ show (typeOf a) ++ ": " ++ show x) in a
  117.  
  118. avar :: IO Dynamic -> IO Thunk
  119. avar expr = aref (toDyn $ adapt expr)
  120. avar_get :: Thunk -> IO Dynamic
  121. avar_get v = do
  122. thnk <- force v
  123. val <- cast thnk
  124. force val
  125.  
  126. avar_set :: Thunk -> IO Dynamic -> IO ()
  127. avar_set v expr = set v (Just . toDyn $ adapt expr)
  128.  
  129. n x = do
  130. putStrLn $ "n " ++ show x
  131. return . toDyn $ (x :: Integer)
  132.  
  133. plus a b = toDyn <$> do
  134. putStrLn $ "plus " ++ show a ++ " " ++ show b
  135. liftA2 ((+) :: Integer -> Integer -> Integer) (cast <$> avar_get a) (cast <$> avar_get b)
  136.  
  137. prt :: Dynamic -> String
  138. prt x = show $ (cast x :: Integer)
  139.  
  140. main = do
  141. n1 <- avar $ n 1
  142. n2 <- avar $ n 2
  143. n3 <- avar $ n 3
  144. p1 <- avar $ n1 `plus` n2
  145. p2 <- avar $ p1 `plus` n3
  146. putStrLn . prt =<< avar_get p1
  147. putStrLn . prt =<< avar_get p2
  148. avar_set n1 (n 5)
  149. putStrLn . prt =<< avar_get p1
  150. avar_set p2 (n3 `plus` p1)
  151. putStrLn . prt =<< avar_get p2
  152. avar_set p1 (n 4)
  153. putStrLn . prt =<< avar_get p2
  154. avar_set p1 (n1 `plus` n2)
  155. putStrLn . prt =<< avar_get p2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement