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开始 类型,但切换功能以外的人(?[cond])square)可能 还通过事件传递新的SF(类型
Event (SF in out)
在 条件满足时(对于'?') [cond] square)。如果是事件,Yampa将使用新的SF 而不是现有的。这个过程是递归的,因为'?' (不能 从图中得到它,除了rSwitch的签名似乎 递归)。
在我查看rSwitch
的源代码之后,看起来它使用switch
以t
被触发时递归切换到相同的init SF(根据该图,虽然我没有看到在源代码中会触发特殊的t
。)
在Yampa Arcade中,它用代码和示例解释了dpSwitch
。关于游戏'Frag'的论文也使用了dpSwitch
。但是,这些教程中似乎没有rSwitch
。所以我真的不知道如何使用r-
或k-
串行开关,以及在什么情况下我们需要它们。
答案 0 :(得分:4)
所有switch
函数都是将信号函数更改为另一种信号函数的方法。我个人觉得Yampa图表有点难以解析,但各种开关的类型签名给出了如何理解它们的良好指示。一旦理解了类型签名,图表就会变得更加清晰。 switch
本身是最基本的:
switch :: SF a (b, Event c) -> (c -> SF a b) -> SF a b
如果我们查看类型,它会准确地告诉我们它的作用:它需要一个SF sf
和一个SF生成器sfg
。 sf
生成类型(b, Event c)
的值,信号函数生成器的输入也恰好是c
类型。因此,每当发生sf
事件时,SF将切换到SF生成器的结果。在事件发生之前,生成的SF将返回原始SF的值。
这个想法也用于rswitch
和kswitch
变体,但有点不同。
rswitch
:这被称为“外部开关”,意味着SF将在不对其输入或输出进行任何分析的情况下进行切换。我们来看一下类型签名:
rswitch :: SF a b -> SF (a, Event (SF a b)) b
它采用单个SF作为类型a
的输入值,并输出类型b
的值。 rswitch
创建一个新的SF,它也会生成输出b
,但需要另外输入Event (SF a b)
类型的输入。请注意,Event值的类型与输入类型匹配。这意味着每当事件发生时,此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 ...
这里,只要AI的移动行为需要改变,aiMovementManager
就会触发事件,事件的值将是移动应该改变的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
有三个参数:sf
,analyzer
和mapping
。 sf
只是标准SF,输入类型为a
,输出类型为b
。 sf
是信号最初的表现方式。 analyzer
是一个SF,它接受sf
的输入和输出,可能会或可能不会触发某些值为c
的事件。如果它没有触发事件,则没有任何反应,SF继续表现为sf
。如果它触发事件,则sf
和事件值都将传递给mapping
,这将确定要切换到的新SF。在根据输出更改系统行为的方式时,kswitch
非常有用。
有用的一个例子是TCP Congestion Avoidance的算法。在这里,我们看看我们是否丢失网络数据包,并提高或降低我们请求数据的速度。