3

有一些Yampa开关的图表在:

http://www.haskell.org/haskellwiki/Yampa/switch

http://www.haskell.org/haskellwiki/Yampa/rSwitch

http://www.haskell.org/haskellwiki/Yampa/kSwitch

(等等)。

我发现,switch唯一一张带有描述的图表,是最容易理解的。其他人似乎很难按照类似的符号来阅读图表。例如,尝试rSwitch使用 中使用的符号读取switch可能是:

是一个递归 SF,它总是被输入一个“in”类型的信号并返回一个“out”类型的信号。从相同类型的初始 SF 开始,但在 switch 函数(?[cond])方块之外的人)也可以通过事件(Event (SF in out)签名处的类型)传递一个新的 SF,同时满足条件(对于 '? ' 在 [cond] 方格之前)。在事件的情况下,Yampa 将使用新的 SF 而不是现有的。这个过程是递归的,因为'?' (不能从图中得到它,除了 rSwitch 的签名似乎是递归的)。

在我查看 的源代码之后rSwitch,它看起来像是switch在触发时递归地切换到相同的 init SF t(根据图中描述的内容,尽管我看不到t源代码中会触发什么特殊内容代码)。

在 Yampa Arcade 中,它dpSwitch通过代码和示例进行了解释。而关于游戏“Frag”的论文也使用了dpSwitch. 然而rSwitch,这些教程中似乎没有。所以我真的不知道如何使用r-k-串行开关,以及在什么情况下我们需要它们。

4

1 回答 1

4

所有这些switch函数都是将信号函数更改为像另一个信号函数一样工作的方法。我个人觉得 Yampa 图有点难以解析,但是各种开关的类型签名很好地说明了如何理解它们。一旦你理解了类型签名,图表就会变得更加清晰。switch本身就是最基本的:

switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b

如果我们查看类型,它会准确地告诉我们它做了什么:它需要一个 SFsf和一个 SF 生成器sfgsf产生 type 的值(b, Event c),而信号函数发生器的输入恰好也是 type 的值c。因此,每当sf' 事件发生时,SF 都会切换到 SF 生成器的结果。在事件发生之前,生成的 SF 将返回原始 SF 的值。

这个想法也用在rswitchandkswitch变体中,但有点不同。


rswitch:这被称为“外部开关”,这意味着 SF 将在不对其输入或输出进行任何分析的情况下进行切换。让我们看一下类型签名:

rswitch :: SF a b -> SF (a, Event (SF a b)) b

它需要一个单一的 SF,作为 type 的输入值和 type 的a输出值brswitch创建一个新的 SF,它也产生输出b,但需要额外的 type 输入Event (SF a b)。请注意,事件值的类型与输入类型匹配。这意味着每当事件发生时,这个 SF 都会切换到那个事件值。但是,SF 的类型仍然存在SF (a, Event (SF a b)) b。这意味着 SF 可以自由地接收带有新 SF 的附加事件,这将影响整个 SF 的行为。一种用途可能是游戏中的 AI 行为:

moveFollowTarget :: SF TargetPosition Velocity
moveShootTarget :: SF TargetPosition Velocity
moveIdle :: SF TargetPosition Velocity

aiMovement :: SF (TargetPosition, Event (SF TargetPosition Velocity)) Velocity
aiMovement = rswitch moveIdle  -- Initially idle...

aiMovementManager :: SF a (Event (SF TargetPosition Velocity))
aiMovementManager = ... whatever ...

在这里,aiMovementManager只要 AI 的运动行为需要改变,就会触发一个事件,事件的值将是运动应该改变到的 SF。


kswitch:这被称为intrinsic switch,因为分析 SF 的内容以确定正确的开关应该是什么。让我们回顾一下类型签名

kswitch :: SF a b -> SF (a, b) (Event c) -> (SF a b -> c -> SF a b) -> SF a b

在这里,kswitch接受三个参数,sfanalyzermappingsf只是一个标准 SF,输入为 type a,输出为 type bsf是信号最初的行为方式。analyzer是一个 SF,它接受输入和输出,sf并且可能会或可能不会触发某种类型的事件,其值为 type c。如果它没有触发事件,那么什么也不会发生,SF 继续表现得像sf. 如果它确实触发了一个事件,那么两者sf和事件值都会被传递给mapping它来确定要切换到的新 SF。kswitch在根据输出改变系统行为方式时很有用。

一个有用的例子是TCP Congestion Avoidance算法。在这里,我们看看我们是否丢失了网络数据包,并提高或降低了我们请求数据的速度。

于 2014-08-20T03:35:31.903 回答