elm スタイルのシグナルに対してシグナル/動作の抽象化を使用する利点はないと思います。ご指摘のとおり、シグナル/動作 API の上にシグナルのみの API を作成することは可能です (まったく使用できる状態ではありませんが、https://github.com/JohnLato/impulse/blob/dyn2/src/を参照してください)。例としてReactive/Impulse/Syntax2.hsを参照)。elm スタイルの API の上にシグナル/動作 API を記述することも可能だと確信しています。これにより、2 つの API は機能的に同等になります。
WRT の効率性。シグナルのみの API を使用する場合、システムには、値が更新されたシグナルのみが再計算を引き起こすメカニズムが必要です (たとえば、マウスを動かさない場合、FRP ネットワークはポインター座標を再計算せず、再描画しません)。スクリーン)。これが行われていれば、シグナルとストリームのアプローチと比較して効率が低下することはないと思います。Elmがこのように機能すると確信しています。
ここでは、継続的な動作の問題が違いを生むとは思いません (またはまったく違います)。振る舞いが時間の経過とともに連続的であると人々が言うことは、それらが常に定義されているということです (つまり、それらは連続的なドメイン上の機能です)。動作自体は連続関数ではありません。しかし、実際にはいつでも動作をサンプリングする方法はありません。それらはイベントに対応する時間にしかサンプリングできないため、この定義の全機能を使用することはできません!
意味的には、次の定義から始めます。
Event == for some t ∈ T: [(t,a)]
Behavior == ∀ t ∈ T: t -> b
動作はイベントが定義されているときにのみサンプリングできるため、イベントが定義されているすべての時間のセットでTX
ある新しいドメインを作成できます。これで、Behavior 定義を次のように緩めることができます。TX
t
Behavior == ∀ t ∈ TX: t -> b
電力を失うことはありません (つまり、これは frp システムの範囲内での元の定義と同等です)。これで、すべての時間を列挙して、TX
これを次のように変換できます。
Behavior == ∀ t ∈ TX: [(t,b)]
Event
これは、ドメインと定量化を除いて元の定義と同じです。の定義域Event
をTX
( の定義によりTX
) に変更し、 の量化をBehavior
(forall から for some に) 変更すると、次のようになります。
Event == for some t ∈ TX: [(t,a)]
Behavior == for some t ∈ TX: [(t,b)]
Event
とnowBehavior
は意味的に同一であるため、明らかに FRP システムで同じ構造を使用して表すことができます。このステップで少し情報が失われます。を区別しないとEvent
、 a が毎回定義されているBehavior
ことがわかりませんが、実際には、これはあまり重要ではないと思います。elm が IIRC で行うことは、s とs の両方が常に値を持つことを要求し、変更されていない場合は前の値を使用することです(つまり、の数量化を変更する代わりに、の数量化を変更します)。Behavior
t
Event
Behavior
Event
Event
forall
Behavior
)。これは、すべてを信号として扱うことができ、すべてがうまく機能することを意味します。信号ドメインがシステムが実際に使用する時間のサブセットになるように実装されているだけです。
このアイデアは、おそらく POPL '14 からの Java での FRP の実装に関する論文 (今は見つけられません。他の誰かがリンクを持っていますか?) で提示されたと思います。記憶に基づいて作業しているため、私の概要は元の証明ほど厳密ではありません。
Behavior
たとえば、より定義されたものを作成することを妨げるものは何もありませんpure someFunction
。これは、FRP システム内ではその余分な定義性を利用できないことを意味するだけなので、より制限された実装によって何も失われることはありません。
時間などの概念的な信号に関しては、典型的なプログラミング言語を使用して実際の連続時間信号を実装することは不可能であることに注意してください。実装は必然的に個別になるため、それをイベント ストリームに変換するのは簡単です。
要するに、信号だけで損をすることはないと思います。