在Elerea,为什么在最后一次国家转型之后,州有没有国家回归?

时间:2016-05-01 10:22:19

标签: haskell frp elerea

让我们来看一下给出的例子 hackage documentation for stateful

do
  smp <- start (stateful "" (:))
  res <- forM "olleh~" smp
  print res

输出是:

["","o","lo","llo","ello","hello"]

它的作用是将一个字符推到下一个字符后进入信号网络,首先是&#39; o&#39;然后&#39; l&#39;,&#39; l&#39;再一次,等等。 给有状态((:),又名cons)的状态转换函数接受一个元素和一个元素列表,并返回带有前置单个元素的列表。 (在Haskell中,StringChar s)的列表

这是怎么回事?

(:) 'o' "" -- gives "o", then
(:) 'l' "o" -- gives "lo", etc

这一切都很简单,但你注意到有一个&#39;〜&#39;在输入字符串的末尾?那么为什么不给出

["","o","lo","llo","ello","hello", "~hello"]
                                    ^^^^^^

可能是因为它首先给出了初始值,然后是第一次调用(:) second 等的结果,等等。所以如果我们输入六个字符(包括&#39;〜 &#39;)我们离开&#34;&#34;在五个字符之后。字符串"~hello"实际上在那里,但在对信号进行采样时,我们得到状态(在它被丢弃之前)。

我期望以下两个(人为的)示例产生相同的输出,但它们不会:

-- 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

所以我的问题是:

  • 为什么这样做?我们获得初始值是否足够重要,我们必须接受这种延迟?
  • 替代函数可以在有效时立即返回下一个值吗? (换句话说,这个替代函数可以在发送之后立即返回&#34;你好&#34;所以可以删除&#39;〜&#39;可以删除吗?)结果信号将永远不会产生初始值。

编辑: 在亚历山大指出我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)

状态&#39;在我的机器上似乎比有状态慢大约25%。

1 个答案:

答案 0 :(得分:1)

  

可能是因为它首先给出了初始值,然后是第一次调用(:)秒的结果等等。所以如果我们输入六个字符(包括'〜'),我们会在五个字符后输出“”前缀。字符串“~hello”实际上在那里,但在对信号进行采样时,我们得到旧状态(在它被丢弃之前)。

这正是stateful的工作原理。引用the documentation

  

初始状态是第一个输出,并且每个后续输出都是从前一个输出和全局参数的值计算的

这回答了你的第一个问题。

至于第二个,是的,替代函数可以立即返回新状态。事实上,有such a function already,称为transfer

  

当前输入影响当前输出,即第一个参数中给出的初始状态被认为出现在第一个输出之前,并且永远不会被观察到。

(它也带有状态,你的例子中你应该忽略它。)

使用此功能,可以像这样重写“hello”示例:

do
  smp <- start (transfer
                 ""
                 (\character _ state -> character:state)
                 (pure undefined))
  res <- forM "olleh" smp
  print res