Basically, I want to be able to write some code like the following:
main = do
x <- newVal (2 :: Int)
y <- newVal (3 :: Int)
z <- newFunc (x, y) (\(a,b) -> a * b)
r1 <- readVal z
print r1 -- prints 6 (2 * 3)
setVal x 5
r2 <- readVal z
print r2 -- prints 15 (5 * 3)
Could someone provide some sample code from scratch or from a library that would allow me to achieve something like the above?
This is almost exactly the functionality of STRef
and IORef
, except as I alluded to in my comment above, you can't get a completely polymorphic newFunc
. You have to do something analagous to liftA2
.
import Data.IORef
main = do
x <- newVal (2 :: Int)
y <- newVal (3 :: Int)
let z = liftIORef2 (x, y) (\(a,b) -> a * b)
r1 <- readVal z
print r1 -- prints 6 (2 * 3)
setVal x 5
r2 <- readVal z
print r2 -- prints 15 (5 * 3)
liftIORef2 (a, b) f = do
a' <- readIORef a
b' <- readIORef b
return (f (a', b'))
newVal = newIORef
setVal = writeIORef
readVal = id
*Main> main
6
15
One can see your program as an example of incremental computing, and here is one solution that uses the library Adaptive, which can be used to express such incremental computing problems.
import Control.Monad.Adaptive (newMod, readMod, inM, change, propagate, run)
main :: IO ()
main = run $ do
x <- newMod $ return 2
y <- newMod $ return 3
z <- newMod $ do
a <- readMod x
b <- readMod y
return (a * b)
newMod $ do -- For observing 'z'
r <- readMod z
inM $ print r
-- prints 6 (2 * 3)
change x 5
propagate -- prints 15 (5 * 3)
The Adaptive library is a Haskell implementation by me that closely follows the nice POPL 2002 paper Adaptive Functional Programming by Acar, Blelloch and Harper.
Instead of newVal
, one uses newMod
, which creates a "modifiable", a computation that keeps track of which other modifiables it depends on when it reads them by readMod
. Later, one can change modifiables by change
followed by propagate
, and all the modifiables that depend on the changed ones automatically gets recomputed in the right order. One can observe what is going on by adding side effects to the computations that define modifiables, and that is how we can see what happens to z
.
You can read more about the Haskell implementation in the paper Monads for Incremental Computing that I wrote for ICFP 2002.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With