gpt4 book ai didi

haskell 网络: wires of wires

转载 作者:行者123 更新时间:2023-12-03 04:38:25 26 4
gpt4 key购买 nike

我正在研究 netwire 包,试图了解 FRP,我有一个简单的问题。

从以下简单的线路开始,我能够每 5 秒(大约)发出一个事件

myWire :: (Monad m, HasTime t s) => Wire s () m a Float
myWire = timeF

myWire' :: (Monad m, HasTime t s) => Wire s () m a Int
myWire' = fmap round myWire

myEvent :: (Monad m, HasTime t s) => Wire s () m a (Event Int)
myEvent = periodic 5 . myWire'

这非常好且直接,但我接下来要做的是将生成的每个事件映射到一条线,然后我可以观看更新。我有一个累加器函数,如下所示:

eventList :: (Monad m, HasTime t s) 
=> Wire s () m a (Event [Wire s () m a Int])
eventList = accumE go [] . myEvent
where go soFar x = f x : soFar
f x = for 10 . pure x --> pure 0

然后,我引入一条新的连线,它将抑制直到 eventList 开始触发事件,如下所示:

myList :: (Monad m, HasTime t s) => Wire s () m a [Wire s () m a Int]
myList = asSoonAs . eventList

所以我已经从事件转到包含电线列表的电线。最后,我引入了一条线来步进每条线并生成结果列表:

myNums :: (Monad m, HasTime t s) => Wire s () m [Wire s () m a Int] [Int]
myNums = mkGen $ \dt wires -> do
stepped <- mapM (\w -> stepWire w dt $ Right undefined) wires
let alive = [ (r, w) | (Right r, w) <- stepped ]
return (Right (map fst alive), myNums)

myNumList :: (Monad m, HasTime t s) => Wire s () m a [Int]
myNumList = myNums . myList

最后,我有一个主要的例程来测试它:

main = testWire clockSession_ myNumList

我期望看到的是一个不断增长的列表,其中列表中的每个元素将显示其创建时间 10 秒,之后该元素将显示零。相反,我得到的是越来越多的静态值列表。例如,我期望在几步之后看到的是

[0]
[5, 0]
[10, 5, 0]
[15, 10, 0, 0]

等等。我实际看到的是

[0]
[5, 0]
[10, 5, 0]
[15, 10, 5, 0]

所以我知道我的累加器功能正在工作:创建的每个事件都被转换为一条线。但我没有看到这些电线随着时间的推移发出不同的值。我的声明 为 10 。 pure x --> pure 0 应该在时间过去后将它们切换为发射 0。

我对 FRP 还很陌生,所以我可能从根本上误解了它的一些重要内容(可能是这样。)

最佳答案

问题在于事件生成的连线不是持久的。 Wire s e m a b 类型的给定值实际上是生成 b 类型值的函数的时间实例来自 a 类型的值。由于 Haskell 使用不可变值,为了步进连线,您必须对 stepWire 中生成的连线执行一些操作。否则,相同的输入会得到相同的输出。看看 myList 的结果:

Event 1: [for 10 . pure 0 --> pure 0]
Event 2: [for 10 . pure 5 --> pure 0, for 10 . pure 0 --> pure 0]
Event 3: [for 10 . pure 10 --> pure 0, for 10 . pure 5 --> pure 0, for 10 . pure 0 --> pure 0]
... etc

当您跨过这些电线时,您只会得到 [.., 10, 5, 0]每次都是因为您正在重用 for 10 . pure x --> pure 0 的原始值金属丝。查看 stepWire 的签名:

stepWire :: Monad m => Wire s e m a b -> s -> Either e a -> m (Either e b, Wire s e m a b)

这意味着对于诸如这样的语句

(result, w') <- stepWire w dt (Right underfined)

...w'应该在下次需要调用 stepWire 时使用,因为它是下一个时间点的行为。如果您有一条可以生产电线的电线,那么您需要将生产的电线卸载到某个地方,以便可以单独处理它们。

对于(我相信)能够为您提供所需行为的程序,请参阅 this code .

$ ghc -o test test.hs
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
$ ./test
[0]
[5,0]
[10,5,0]
[15,10,0,0]
[20,15,0,0,0]
...

关于 haskell 网络: wires of wires,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28918915/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com