【发布时间】:2016-05-01 10:22:18
【问题描述】:
让我们看一下 hackage documentation for stateful
do
smp <- start (stateful "" (:))
res <- forM "olleh~" smp
print res
输出是:
["","o","lo","llo","ello","hello"]
它的作用是将一个字符一个接一个地推入信号网络,首先是'o',然后是'l',再是'l',以此类推。
赋予有状态的状态转换函数((:),又名cons)接受一个元素和一个元素列表,并返回带有单个元素的列表。 (在 Haskell 中,String 是 Chars 的列表)
这是怎么回事
(:) 'o' "" -- gives "o", then
(:) 'l' "o" -- gives "lo", etc
这一切都很简单,但是您是否注意到输入字符串的末尾有一个“~”?那为什么不给呢
["","o","lo","llo","ello","hello", "~hello"]
^^^^^^
?
可能是因为它首先给出初始值,然后是第一次调用(:)second的结果,等等。所以如果我们输入六个字符(包括'~'),我们就会退出五个字符后的 "" 已预先添加。字符串"~hello" 实际上在那里,但是在对信号进行采样时,我们得到了 old 状态(就在它被丢弃之前)。
我希望以下两个(人为的)示例产生相同的输出,但事实并非如此:
-- 1
do
smp <- start $ do
n <- input
return (n*2)
res <- forM [1,2,3] smp
print res -- prints [2,4,6]
-- 2
do
smp <- start $ stateful 0 (\n _ -> n*2) -- ignore state
res <- forM [1,2,3] smp
print res -- prints [0,2,4]
-- edit: 3
-- to make the trio complete, you can use transfer to do the same
-- thing as 1 above
-- there is of course no reason to actually do it this way
do
smp <- start $ transfer undefined (\n _ _ -> n*2) (pure undefined)
res <- forM [1,2,3] smp
print res
所以我的问题是:
- 为什么要这样做?我们获得的初始值是否足够重要,以至于我们必须接受这种延迟?
- 替代函数是否可以在下一个值可用时立即返回? (换句话说,这个替代函数是否可以在发送“h”后立即返回“hello”,因此可以删除“~”?)结果信号将永远不会产生初始值。
编辑: 在 Alexander 向我指出 transfer 之后,我想到了这个:
do
smp <- start (stateful' "" (:))
res <- forM "olleh" smp -- no '~'!
print res -- prints ["o","lo","llo","ello","hello"]
stateful' :: a -> (p -> a -> a) -> SignalGen p (Signal a)
stateful' s f = transfer s (\p _ a -> f p a) (pure undefined)
stateful' 在我的机器上似乎比 stateful 慢了大约 25%。
【问题讨论】: