Haskell 自动重新计算结果

Haskell 自动重新计算结果,haskell,reactive-programming,Haskell,Reactive Programming,基本上,我希望能够编写如下代码: 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) m

基本上,我希望能够编写如下代码:

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)
main=do

x这几乎就是
STRef
IORef
的功能,除非我在上面的评论中提到,否则您无法获得完全多态的
newFunc
。你必须做一些有助于提升的事情

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
import Data.IORef
main=do

希望有人能给你一个FRP答案,现在我将向你展示如何用STM制作反应系统

首先,我们需要显式声明事务变量,并设置生产者和消费者。本例中的“生产者”是您的
newFunc
,它读取
x
y
以产生新的
z
。“消费者”读取
z
,并在更改后打印

import Control.Concurrent.STM
import Control.Concurrent
import Control.Monad

f = do
  x <- newTVarIO 2
  y <- newTVarIO 3
  z <- newTVarIO 0
  forkIO $ newFunc 2 3 (x,y) z
  loop z 0
这种简单的读取比较模式{retry或compute}功能强大,正是
newFunc
所需要的。我们将读取所有值,并在输入未更改且结果正确的情况下重试(调整此值以满足您的需要)

newFunc::Int->Int->(TVar Int,TVar Int)->TVar Int->IO()
newFunc xV yV(x,y)z=原子级$do

newX您可以将您的程序视为增量计算的一个示例,下面是一个使用库的解决方案,它可以用来表示此类增量计算问题

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)
import Control.Monad.Adaptive(newMod、readMod、inM、更改、传播、运行)
main::IO()
main=run$do

你到底想实现什么?什么是
newVal
newFunc
setVal
等等?@Sibi根据我的反应式编程经验,我猜,
newVal
创建了一个可以/将要改变的值(想想电子表格的一个单元格),而
newFunc
创建了一个“公式”并将结果存储在
z
中,以便在
setVal
anything@sibijozefg是正确的。你定义它们,它们只是为了说明的目的。预期的输出应该清楚地表明我正在努力实现的目标,我不介意你提出一个稍微有点小的方法different@Clinton:您必须接受对语法的一些更改,因为请注意,
x@TomEllis中的值是No,newVal中的x将是IOref或STref,不是实际值。语法确实有道理。
newFunc :: Int -> Int -> (TVar Int , TVar Int) -> TVar Int -> IO ()
newFunc xV yV (x, y) z = atomically $ do
  newX  <- readTVar x
  newY  <- readTVar y
  currZ <- readTVar z
  let result = newX * newY
  when (newX == xV && newY == yV && currZ == result) retry
  writeTVar z result
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)